* [PATCHv1 0/8] unicore32 machine related files: summary
@ 2011-01-06 7:56 Guan Xuetao
2011-01-06 8:00 ` Guan Xuetao
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Guan Xuetao @ 2011-01-06 7:56 UTC (permalink / raw)
To: linux-arch, linux-kernel
From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
The whole patch could be fetched from:
git://git.kernel.org/pub/scm/linux/kernel/git/epip/unicore32.git
with branch name: unicore32.
And it is divided into three patch sets: core architecture files,
additional architecture files, and machine related files.
This patch set adds the machine related files for UniCore32 ISA and PKUnity SoC.
Patch 1 adds machine related core files, also including build infrastructure.
Patch 2 add all hardware registers definitions, which are not split and inserted into
different drivers.
Patch 3 implements arch-specific pci bus driver.
Patch 4 implements arch-specific ps2 dirver.
Patch 5 implements frame buffer driver.
Patch 6 implements ac97 driver.
Patch 7 implements arch-specific i2c bus driver.
Patch 8 implements network driver.
Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
---
arch/unicore32/include/asm/mach/PKUnity.h | 104 ++
arch/unicore32/include/asm/mach/bitfield.h | 24 +
arch/unicore32/include/asm/mach/hardware.h | 45 +
arch/unicore32/include/asm/mach/regs-ac97.h | 32 +
arch/unicore32/include/asm/mach/regs-dmac.h | 81 +
arch/unicore32/include/asm/mach/regs-gpio.h | 70 +
arch/unicore32/include/asm/mach/regs-i2c.h | 63 +
arch/unicore32/include/asm/mach/regs-intc.h | 28 +
arch/unicore32/include/asm/mach/regs-nand.h | 79 +
arch/unicore32/include/asm/mach/regs-ost.h | 92 ++
arch/unicore32/include/asm/mach/regs-pci.h | 94 ++
arch/unicore32/include/asm/mach/regs-pm.h | 126 ++
arch/unicore32/include/asm/mach/regs-ps2.h | 20 +
arch/unicore32/include/asm/mach/regs-resetc.h | 34 +
arch/unicore32/include/asm/mach/regs-rtc.h | 37 +
arch/unicore32/include/asm/mach/regs-sdc.h | 156 ++
arch/unicore32/include/asm/mach/regs-spi.h | 98 ++
arch/unicore32/include/asm/mach/regs-uart.h | 3 +
arch/unicore32/include/asm/mach/regs-umal.h | 229 +++
arch/unicore32/include/asm/mach/regs-unigfx.h | 200 +++
arch/unicore32/include/asm/pci.h | 46 +
arch/unicore32/kernel/pci.c | 404 +++++
arch/unicore32/kernel/puv3-core.c | 266 ++++
arch/unicore32/kernel/puv3-nb0916.c | 183 +++
arch/unicore32/kernel/puv3-smw0919.c | 120 ++
drivers/input/keyboard/Kconfig | 11 +
drivers/input/keyboard/atkbd.c | 4 +
drivers/input/mouse/psmouse-base.c | 41 +
drivers/input/serio/i8042.h | 2 +
drivers/pci/Makefile | 1 +
drivers/staging/puv3/Kconfig | 142 ++
drivers/staging/puv3/Makefile | 27 +
drivers/staging/puv3/TODO | 7 +
drivers/staging/puv3/i8042-ucio.h | 96 ++
drivers/staging/puv3/nb0916-atkbd.h | 43 +
drivers/staging/puv3/puv3_ac97.c | 383 +++++
drivers/staging/puv3/puv3_i2c.c | 325 ++++
drivers/staging/puv3/puv3_pcm.c | 449 ++++++
drivers/staging/puv3/puv3_pcm.h | 33 +
drivers/staging/puv3/puv3_umal.c | 2082 +++++++++++++++++++++++++
drivers/staging/puv3/puv3_unifb.c | 972 ++++++++++++
include/linux/fb.h | 2 +
42 files changed, 7254 insertions(+), 0 deletions(-)
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCHv1 0/8] unicore32 machine related files: summary
2011-01-06 7:56 [PATCHv1 0/8] unicore32 machine related files: summary Guan Xuetao
@ 2011-01-06 8:00 ` Guan Xuetao
2011-01-06 8:02 ` Guan Xuetao
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Guan Xuetao @ 2011-01-06 8:00 UTC (permalink / raw)
To: linux-arch, linux-kernel
[PATCHv1 1/8] unicore32 machine related files: core files
From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
Patch 1 adds machine related core files, also including build infrastructure.
Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
---
arch/unicore32/kernel/puv3-core.c | 266 ++++++++++++++++++++++++++++++++++
arch/unicore32/kernel/puv3-nb0916.c | 183 +++++++++++++++++++++++
arch/unicore32/kernel/puv3-smw0919.c | 120 +++++++++++++++
drivers/staging/puv3/Kconfig | 142 ++++++++++++++++++
drivers/staging/puv3/Makefile | 27 ++++
drivers/staging/puv3/TODO | 7 +
6 files changed, 745 insertions(+), 0 deletions(-)
diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
new file mode 100644
index 0000000..c5cc2f2
--- /dev/null
+++ b/arch/unicore32/kernel/puv3-core.c
@@ -0,0 +1,266 @@
+/*
+ * linux/arch/unicore32/kernel/puv3-core.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ * Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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.
+ *
+ * Contributors & Additions/Fixes:
+ * 2009-04: First version by GUAN Xue-tao
+ * 2009-07-21: add uart resources definitions by HU Dong-liang
+ *
+ * TODO:
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/amba/bus.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/mach/hardware.h>
+#include <asm/irq.h>
+#include <linux/cnt32_to_63.h>
+#include <linux/usb/musb.h>
+#include <asm/mach/pm.h>
+
+/*
+ * This is the PKUnity sched_clock implementation. This has
+ * a resolution of 271ns, and a maximum value of 32025597s (370 days).
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 582 seconds between successive
+ * calls to this function.
+ *
+ * ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
+ */
+unsigned long long sched_clock(void)
+{
+ unsigned long long v = cnt32_to_63(OST_OSCR);
+
+ /* original conservative method, but overflow frequently
+ * v *= NSEC_PER_SEC >> 12;
+ * do_div(v, CLOCK_TICK_RATE >> 12);
+ */
+ v = ((v & 0x7fffffffffffffffULL) * 2235) >> 5;
+
+ return v;
+}
+
+static struct resource puv3_usb_resources[] = {
+ /* order is significant! */
+ {
+ .start = PKUNITY_USB_BASE,
+ .end = PKUNITY_USB_BASE + 0x3ff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_USB,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = IRQ_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct musb_hdrc_config puv3_usb_config[] = {
+ {
+ .num_eps = 16,
+ .multipoint = 1,
+#ifdef CONFIG_USB_INVENTRA_DMA
+ .dma = 1,
+ .dma_channels = 8,
+#endif
+ },
+};
+
+static struct musb_hdrc_platform_data puv3_usb_plat = {
+ .mode = MUSB_HOST,
+ .min_power = 100,
+ .clock = 0,
+ .config = puv3_usb_config,
+};
+
+static struct resource puv3_mmc_resources[] = {
+ [0] = {
+ .start = PKUNITY_SDC_BASE,
+ .end = PKUNITY_SDC_BASE + 0xfff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SDC,
+ .end = IRQ_SDC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource puv3_rtc_resources[] = {
+ [0] = {
+ .start = PKUNITY_RTC_BASE,
+ .end = PKUNITY_RTC_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_RTCAlarm,
+ .end = IRQ_RTCAlarm,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = IRQ_RTC,
+ .end = IRQ_RTC,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct resource puv3_pwm_resources[] = {
+ [0] = {
+ .start = PKUNITY_OST_BASE + 0x80,
+ .end = PKUNITY_OST_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource puv3_uart0_resources[] = {
+ [0] = {
+ .start = PKUNITY_UART0_BASE,
+ .end = PKUNITY_UART0_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_UART0,
+ .end = IRQ_UART0,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct resource puv3_uart1_resources[] = {
+ [0] = {
+ .start = PKUNITY_UART1_BASE,
+ .end = PKUNITY_UART1_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_UART1,
+ .end = IRQ_UART1,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct resource puv3_umal_resources[] = {
+ [0] = {
+ .start = PKUNITY_UMAL_BASE,
+ .end = PKUNITY_UMAL_BASE + 0x1fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_UMAL,
+ .end = IRQ_UMAL,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+#ifdef CONFIG_PUV3_PM
+
+#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
+#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
+
+/*
+ * List of global PXA peripheral registers to preserve.
+ * More ones like CP and general purpose register values are preserved
+ * with the stack pointer in sleep.S.
+ */
+enum {
+ SLEEP_SAVE_PM_PLLDDRCFG,
+ SLEEP_SAVE_COUNT
+};
+
+
+static void puv3_cpu_pm_save(unsigned long *sleep_save)
+{
+/* SAVE(PM_PLLDDRCFG); */
+}
+
+static void puv3_cpu_pm_restore(unsigned long *sleep_save)
+{
+/* RESTORE(PM_PLLDDRCFG); */
+}
+
+static int puv3_cpu_pm_prepare(void)
+{
+ /* set resume return address */
+ PM_DIVCFG = virt_to_phys(puv3_cpu_resume);
+ return 0;
+}
+
+static void puv3_cpu_pm_enter(suspend_state_t state)
+{
+ /* Clear reset status */
+ RESETC_RSSR = RESETC_RSSR_HWR | RESETC_RSSR_WDR
+ | RESETC_RSSR_SMR | RESETC_RSSR_SWR;
+
+ switch (state) {
+/* case PM_SUSPEND_ON:
+ puv3_cpu_idle();
+ break; */
+ case PM_SUSPEND_MEM:
+ puv3_cpu_pm_prepare();
+ puv3_cpu_suspend(PM_PMCR_SFB);
+ break;
+ }
+}
+
+static int puv3_cpu_pm_valid(suspend_state_t state)
+{
+ return state == PM_SUSPEND_MEM;
+}
+
+static void puv3_cpu_pm_finish(void)
+{
+ /* ensure not to come back here if it wasn't intended */
+ /* PSPR = 0; */
+}
+
+static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss = {
+ .save_count = SLEEP_SAVE_COUNT,
+ .valid = puv3_cpu_pm_valid,
+ .save = puv3_cpu_pm_save,
+ .restore = puv3_cpu_pm_restore,
+ .enter = puv3_cpu_pm_enter,
+ .prepare = puv3_cpu_pm_prepare,
+ .finish = puv3_cpu_pm_finish,
+};
+
+static void __init puv3_init_pm(void)
+{
+ puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
+}
+#else
+static inline void puv3_init_pm(void) {}
+#endif
+
+void __init puv3_core_init(void)
+{
+ puv3_init_pm();
+ platform_device_register_simple("PKUnity-v3-RTC", -1,
+ puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));
+ platform_device_register_simple("PKUnity-v3-UMAL", -1,
+ puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
+ platform_device_register_simple("PKUnity-v3-MMC", -1,
+ puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
+ platform_device_register_simple("PKUnity-v3-PWM", -1,
+ puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
+ platform_device_register_simple("PKUnity-v3-UART", 0,
+ puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));
+ platform_device_register_simple("PKUnity-v3-UART", 1,
+ puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
+ platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
+ platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
+ puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
+ &puv3_usb_plat, sizeof(puv3_usb_plat));
+}
+
diff --git a/arch/unicore32/kernel/puv3-nb0916.c b/arch/unicore32/kernel/puv3-nb0916.c
new file mode 100644
index 0000000..b5e48d4
--- /dev/null
+++ b/arch/unicore32/kernel/puv3-nb0916.c
@@ -0,0 +1,183 @@
+/*
+ * linux/arch/unicore32/kernel/puv3-nb0916.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ * Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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.
+ *
+ * Contributors & Additions/Fixes:
+ * 2009-07-02: add gpio key support by HUANG Tao
+ * 2009-05-14: add i2c board info support by ZHONG Qi
+ * 2009-05-10: First version by GUAN Xue-tao
+ *
+ * TODO:
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/hardware.h>
+
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+
+static struct physmap_flash_data physmap_flash_data = {
+ .width = 1,
+};
+
+static struct resource physmap_flash_resource = {
+ .start = 0xFFF80000,
+ .end = 0xFFFFFFFF,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device physmap_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &physmap_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &physmap_flash_resource,
+};
+
+static struct resource puv3_i2c_resources[] = {
+ [0] = {
+ .start = PKUNITY_I2C_BASE,
+ .end = PKUNITY_I2C_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_I2C,
+ .end = IRQ_I2C,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device puv3_device_i2c = {
+ .name = "PKUnity-v3-I2C",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(puv3_i2c_resources),
+ .resource = puv3_i2c_resources,
+};
+
+static struct platform_pwm_backlight_data nb0916_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 100,
+ .dft_brightness = 100,
+ .pwm_period_ns = 70 * 1024,
+};
+
+static struct platform_device nb0916_device_backlight = {
+ .name = "pwm-backlight",
+ .id = 0,
+ .dev = {
+ .platform_data = &nb0916_backlight_data,
+ },
+};
+
+static struct gpio_keys_button nb0916_gpio_keys[] = {
+ {
+ .type = EV_KEY,
+ .code = KEY_POWER,
+ .gpio = GPI_SOFF_REQ,
+ .desc = "Power Button",
+ .wakeup = 1,
+ .active_low = 1,
+ },
+ {
+ .type = EV_KEY,
+ .code = BTN_TOUCH,
+ .gpio = GPI_BTN_TOUCH,
+ .desc = "Touchpad Button",
+ .wakeup = 1,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data nb0916_gpio_button_data = {
+ .buttons = nb0916_gpio_keys,
+ .nbuttons = ARRAY_SIZE(nb0916_gpio_keys),
+};
+
+static struct platform_device nb0916_device_gpio_button = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &nb0916_gpio_button_data,
+ },
+};
+
+static struct platform_device *mach_nb0916_devices[] __initdata = {
+ &puv3_device_i2c,
+ &physmap_flash,
+ &nb0916_device_backlight,
+ &nb0916_device_gpio_button,
+};
+
+static irqreturn_t nb0916_lcdcaseoff_handler(int irq, void *dev_id)
+{
+ if (gpio_get_value(GPI_LCD_CASE_OFF))
+ gpio_set_value(GPO_LCD_EN, 1);
+ else
+ gpio_set_value(GPO_LCD_EN, 0);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t nb0916_overheat_handler(int irq, void *dev_id)
+{
+ machine_halt();
+ /* SYSTEM HALT, NO RETURN */
+ return IRQ_HANDLED;
+}
+
+static struct i2c_board_info __initdata puv3_i2c_devices[] = {
+ { I2C_BOARD_INFO("lm75", I2C_TAR_THERMAL), },
+ { I2C_BOARD_INFO("bq27200", I2C_TAR_PWIC), },
+ { I2C_BOARD_INFO("24c02", I2C_TAR_EEPROM), },
+};
+
+int __init mach_nb0916_init(void)
+{
+ i2c_register_board_info(0, puv3_i2c_devices,
+ ARRAY_SIZE(puv3_i2c_devices));
+
+ platform_add_devices(mach_nb0916_devices,
+ ARRAY_SIZE(mach_nb0916_devices));
+
+ if (request_irq(gpio_to_irq(GPI_LCD_CASE_OFF),
+ &nb0916_lcdcaseoff_handler,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "NB0916 lcd case off", NULL) < 0) {
+
+ printk(KERN_DEBUG "LCD-Case-OFF IRQ %d not available\n",
+ gpio_to_irq(GPI_LCD_CASE_OFF));
+ }
+
+ if (request_irq(gpio_to_irq(GPI_OTP_INT), &nb0916_overheat_handler,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "NB0916 overheating protection", NULL) < 0) {
+
+ printk(KERN_DEBUG "Overheating Protection IRQ %d not available\n",
+ gpio_to_irq(GPI_OTP_INT));
+ }
+
+ return 0;
+}
+
+subsys_initcall_sync(mach_nb0916_init);
diff --git a/arch/unicore32/kernel/puv3-smw0919.c b/arch/unicore32/kernel/puv3-smw0919.c
new file mode 100644
index 0000000..bdf7ae2
--- /dev/null
+++ b/arch/unicore32/kernel/puv3-smw0919.c
@@ -0,0 +1,120 @@
+/*
+ * linux/arch/unicore32/kernel/puv3-smw0919.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ * Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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.
+ *
+ * Contributors & Additions/Fixes:
+ * 2009-07-23: First version by SU Yong-gang
+ *
+ * TODO:
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+
+#include <mach/hardware.h>
+
+static struct physmap_flash_data physmap_flash_data = {
+ .width = 1,
+};
+
+static struct resource physmap_flash_resource = {
+ .start = 0xFFF80000,
+ .end = 0xFFFFFFFF,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device physmap_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &physmap_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &physmap_flash_resource,
+};
+
+static struct resource puv3_i2c_resources[] = {
+ [0] = {
+ .start = PKUNITY_I2C_BASE,
+ .end = PKUNITY_I2C_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_I2C,
+ .end = IRQ_I2C,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device puv3_device_i2c = {
+ .name = "PKUnity-v3-I2C",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(puv3_i2c_resources),
+ .resource = puv3_i2c_resources,
+};
+
+static struct gpio_keys_button smw0919_gpio_keys[] = {
+ {
+ .type = EV_KEY,
+ .code = KEY_POWER,
+ .gpio = GPI_SOFF_REQ,
+ .desc = "Power Button",
+ .wakeup = 1,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data smw0919_power_button_data = {
+ .buttons = smw0919_gpio_keys,
+ .nbuttons = ARRAY_SIZE(smw0919_gpio_keys),
+};
+
+static struct platform_device smw0919_device_power_button = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &smw0919_power_button_data,
+ },
+};
+
+static struct platform_device *mach_smw0919_devices[] __initdata = {
+ &puv3_device_i2c,
+ &physmap_flash,
+ &smw0919_device_power_button,
+};
+
+static struct i2c_board_info __initdata puv3_i2c_devices[] = {
+ { I2C_BOARD_INFO("lm75", I2C_TAR_THERMAL), },
+ { I2C_BOARD_INFO("24c02", I2C_TAR_EEPROM), },
+};
+
+int __init mach_smw0919_init(void)
+{
+ i2c_register_board_info(0, puv3_i2c_devices,
+ ARRAY_SIZE(puv3_i2c_devices));
+
+ platform_add_devices(mach_smw0919_devices,
+ ARRAY_SIZE(mach_smw0919_devices));
+
+ return 0;
+}
+
+subsys_initcall_sync(mach_smw0919_init);
diff --git a/drivers/staging/puv3/Kconfig b/drivers/staging/puv3/Kconfig
new file mode 100644
index 0000000..54c876b
--- /dev/null
+++ b/drivers/staging/puv3/Kconfig
@@ -0,0 +1,142 @@
+#
+# PKUnity v3 Kconfig
+#
+
+if ARCH_PUV3
+
+menu "PKUnity v3 SoC Features"
+
+config PUV3_GPIO
+ bool
+ depends on !ARCH_FPGA
+ select GENERIC_GPIO
+ select GPIO_SYSFS if EXPERIMENTAL
+ default y
+
+config PUV3_PWM
+ tristate
+ default BACKLIGHT_PWM
+ help
+ Enable support for NB0916 PWM controllers
+
+config PUV3_RTC
+ tristate "PKUnity v3 RTC Support"
+ depends on !ARCH_FPGA
+
+config PUV3_I2C
+ bool "PKUnity v3 I2C bus support"
+# default y
+ select I2C
+ select I2C_CHARDEV
+ select I2C_ALGOBIT
+
+config PUV3_UMAL
+ tristate "PKUnity v3 UMAL Gigabit Network Adapter support"
+ select MII
+ select PHYLIB
+
+config PUV3_UNIGFX
+ tristate "PKUnity v3 Unigfx display support"
+ select FB
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ help
+ Choose this option if you want to use the Unigfx device as a
+ framebuffer device. Without the support of PCI & AGP.
+
+config PUV3_UNIGFX_HWACCEL
+ bool "PKUnity v3 Unigfx hardware accelerator support"
+ depends on PUV3_UNIGFX
+
+config PUV3_AC97
+ tristate "PKUnity v3 AC97 driver support"
+ select SND_PCM
+ select SND_AC97_CODEC
+ help
+ Say Y or M if you want to support any AC97 codec attached to
+ the PKUnity AC97 interface.
+
+#config PUV3_MUSB
+# bool "PKUnity v3 USB MUSBMHDRC Support"
+# select USB_MUSB_HDRC_HCD
+# select USB_MUSB_HOST
+# select MUSB_PIO_ONLY
+# select USB_INVENTRA_DMA
+
+#config PUV3_MMC
+# tristate "PKUnity v3 MMC/SD Card support"
+# select MMC
+
+#config PUV3_NAND
+# tristate "PKUnity v3 NAND Flash support"
+# select MTD
+# select MTD_PARTITIONS
+# select MTD_NAND
+# select MTD_CHAR
+# select MTD_BLOCK
+
+#config PUV3_NAND_CHIPNR
+# int "PKUnity v3 NAND Flash Chip number (1-4)"
+# range 1 4
+# depends on PUV3_NAND
+# default "1"
+
+#config PUV3_UART
+# bool "PKUnity v3 serial port support"
+# select SERIAL_CORE
+
+#config PUV3_UART_CONSOLE
+# bool "Console on PKUnity serial port"
+# depends on PUV3_UART
+# select SERIAL_CORE_CONSOLE
+# help
+# Even if you say Y here, the currently visible virtual console
+# (/dev/tty0) will still be used as the system console by default, but
+# you can alter that using a kernel command line option such as
+# "console=ttySA0". (Try "man bootparam" or see the documentation of
+# your boot loader (lilo or loadlin) about how to pass options to the
+# kernel at boot time.)
+
+#config PUV3_SPI
+# bool "PKUnity v3 SPI controller support"
+# select SPI
+# select SPI_MASTER
+
+endmenu
+
+if PUV3_NB0916
+
+menu "PKUnity NetBook-0916 Features"
+
+config I2C_BATTERY_BQ27200
+ tristate "I2C Battery BQ27200 Support"
+ select PUV3_I2C
+ select POWER_SUPPLY
+ select BATTERY_BQ27x00
+
+config I2C_EEPROM_AT24
+ tristate "I2C EEPROMs AT24 support"
+ select PUV3_I2C
+ select MISC_DEVICES
+ select EEPROM_AT24
+
+config LCD_BACKLIGHT
+ tristate "LCD Backlight support"
+ select BACKLIGHT_LCD_SUPPORT
+ select BACKLIGHT_PWM
+
+#config USB_WLAN_HED_AQ3
+# tristate "HED Wireless Interface Card"
+# select WIRELESS_EXT
+# select WIRELESS_EXT_SYSFS
+
+#config USB_CMMB_INNOFIDEI
+# tristate "Innofidei cmmb dongle"
+
+endmenu
+
+endif
+
+endif
diff --git a/drivers/staging/puv3/Makefile b/drivers/staging/puv3/Makefile
new file mode 100644
index 0000000..e14fc95
--- /dev/null
+++ b/drivers/staging/puv3/Makefile
@@ -0,0 +1,27 @@
+#
+# Makefile for the Linux-uc PKUnity v3 Platform
+#
+# 2008~2010, Epip.Guan
+#
+
+obj-y := puv3_dma.o
+
+obj-$(CONFIG_PUV3_GPIO) += puv3_gpio.o
+obj-$(CONFIG_PUV3_RTC) += puv3_rtc.o
+obj-$(CONFIG_PUV3_I2C) += puv3_i2c.o
+obj-$(CONFIG_PUV3_UMAL) += puv3_umal.o
+obj-$(CONFIG_PUV3_UNIGFX) += puv3_unifb.o
+obj-$(CONFIG_PUV3_PWM) += puv3_pwm.o
+obj-$(CONFIG_PUV3_AC97) += puv3_sound.o
+puv3_sound-objs := puv3_ac97.o puv3_pcm.o
+
+# drivers need upgrade and review
+#obj-$(CONFIG_PUV3_MMC) += puv3_mmc.o
+#obj-$(CONFIG_PUV3_NAND) += puv3_nand.o
+#obj-$(CONFIG_PUV3_UART) += puv3_uart.o
+#obj-$(CONFIG_PUV3_SPI) += puv3_spi.o
+
+# drivers from partners
+#obj-$(CONFIG_USB_WLAN_HED_AQ3) += hed-aq3/
+#obj-$(CONFIG_USB_CMMB_INNOFIDEI) += usb-innofidei.o
+
diff --git a/drivers/staging/puv3/TODO b/drivers/staging/puv3/TODO
new file mode 100644
index 0000000..f89d034
--- /dev/null
+++ b/drivers/staging/puv3/TODO
@@ -0,0 +1,7 @@
+- The driver in this directory has been tested on Netbook 0916 with latest linux version.
+- Following drivers are not included for not testing with latest linux version, but only in 2.6.32.
+ - UART, SPI, NAND, SDC
+- Please use the following link to get information about the SoC's details.
+ http://www.pkunity.com/english%20version/engindex.htm
+- Please send any patches or advice to
+ - Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
> -----Original Message-----
> From: linux-arch-owner@vger.kernel.org [mailto:linux-arch-owner@vger.kernel.org] On Behalf Of Guan Xuetao
> Sent: Thursday, January 06, 2011 3:57 PM
> To: linux-arch@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [PATCHv1 0/8] unicore32 machine related files: summary
>
> From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
>
> The whole patch could be fetched from:
> git://git.kernel.org/pub/scm/linux/kernel/git/epip/unicore32.git
> with branch name: unicore32.
> And it is divided into three patch sets: core architecture files,
> additional architecture files, and machine related files.
>
> This patch set adds the machine related files for UniCore32 ISA and PKUnity SoC.
>
> Patch 1 adds machine related core files, also including build infrastructure.
>
> Patch 2 add all hardware registers definitions, which are not split and inserted into
> different drivers.
>
> Patch 3 implements arch-specific pci bus driver.
>
> Patch 4 implements arch-specific ps2 dirver.
>
> Patch 5 implements frame buffer driver.
>
> Patch 6 implements ac97 driver.
>
> Patch 7 implements arch-specific i2c bus driver.
>
> Patch 8 implements network driver.
>
> Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
> ---
> arch/unicore32/include/asm/mach/PKUnity.h | 104 ++
> arch/unicore32/include/asm/mach/bitfield.h | 24 +
> arch/unicore32/include/asm/mach/hardware.h | 45 +
> arch/unicore32/include/asm/mach/regs-ac97.h | 32 +
> arch/unicore32/include/asm/mach/regs-dmac.h | 81 +
> arch/unicore32/include/asm/mach/regs-gpio.h | 70 +
> arch/unicore32/include/asm/mach/regs-i2c.h | 63 +
> arch/unicore32/include/asm/mach/regs-intc.h | 28 +
> arch/unicore32/include/asm/mach/regs-nand.h | 79 +
> arch/unicore32/include/asm/mach/regs-ost.h | 92 ++
> arch/unicore32/include/asm/mach/regs-pci.h | 94 ++
> arch/unicore32/include/asm/mach/regs-pm.h | 126 ++
> arch/unicore32/include/asm/mach/regs-ps2.h | 20 +
> arch/unicore32/include/asm/mach/regs-resetc.h | 34 +
> arch/unicore32/include/asm/mach/regs-rtc.h | 37 +
> arch/unicore32/include/asm/mach/regs-sdc.h | 156 ++
> arch/unicore32/include/asm/mach/regs-spi.h | 98 ++
> arch/unicore32/include/asm/mach/regs-uart.h | 3 +
> arch/unicore32/include/asm/mach/regs-umal.h | 229 +++
> arch/unicore32/include/asm/mach/regs-unigfx.h | 200 +++
> arch/unicore32/include/asm/pci.h | 46 +
> arch/unicore32/kernel/pci.c | 404 +++++
> arch/unicore32/kernel/puv3-core.c | 266 ++++
> arch/unicore32/kernel/puv3-nb0916.c | 183 +++
> arch/unicore32/kernel/puv3-smw0919.c | 120 ++
> drivers/input/keyboard/Kconfig | 11 +
> drivers/input/keyboard/atkbd.c | 4 +
> drivers/input/mouse/psmouse-base.c | 41 +
> drivers/input/serio/i8042.h | 2 +
> drivers/pci/Makefile | 1 +
> drivers/staging/puv3/Kconfig | 142 ++
> drivers/staging/puv3/Makefile | 27 +
> drivers/staging/puv3/TODO | 7 +
> drivers/staging/puv3/i8042-ucio.h | 96 ++
> drivers/staging/puv3/nb0916-atkbd.h | 43 +
> drivers/staging/puv3/puv3_ac97.c | 383 +++++
> drivers/staging/puv3/puv3_i2c.c | 325 ++++
> drivers/staging/puv3/puv3_pcm.c | 449 ++++++
> drivers/staging/puv3/puv3_pcm.h | 33 +
> drivers/staging/puv3/puv3_umal.c | 2082 +++++++++++++++++++++++++
> drivers/staging/puv3/puv3_unifb.c | 972 ++++++++++++
> include/linux/fb.h | 2 +
> 42 files changed, 7254 insertions(+), 0 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCHv1 0/8] unicore32 machine related files: summary
2011-01-06 7:56 [PATCHv1 0/8] unicore32 machine related files: summary Guan Xuetao
2011-01-06 8:00 ` Guan Xuetao
@ 2011-01-06 8:02 ` Guan Xuetao
2011-01-06 8:03 ` Guan Xuetao
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Guan Xuetao @ 2011-01-06 8:02 UTC (permalink / raw)
To: linux-arch, linux-kernel
[PATCHv1 2/8] unicore32 machine related files: hardware registers
From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
Patch 2 adds all hardware registers definitions, which are not split and inserted into
different drivers.
Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
---
arch/unicore32/include/asm/mach/PKUnity.h | 104 +++++++++++
arch/unicore32/include/asm/mach/bitfield.h | 24 +++
arch/unicore32/include/asm/mach/hardware.h | 45 +++++
arch/unicore32/include/asm/mach/regs-ac97.h | 32 ++++
arch/unicore32/include/asm/mach/regs-dmac.h | 81 +++++++++
arch/unicore32/include/asm/mach/regs-gpio.h | 70 ++++++++
arch/unicore32/include/asm/mach/regs-i2c.h | 63 +++++++
arch/unicore32/include/asm/mach/regs-intc.h | 28 +++
arch/unicore32/include/asm/mach/regs-nand.h | 79 +++++++++
arch/unicore32/include/asm/mach/regs-ost.h | 92 ++++++++++
arch/unicore32/include/asm/mach/regs-pci.h | 94 ++++++++++
arch/unicore32/include/asm/mach/regs-pm.h | 126 ++++++++++++++
arch/unicore32/include/asm/mach/regs-ps2.h | 20 +++
arch/unicore32/include/asm/mach/regs-resetc.h | 34 ++++
arch/unicore32/include/asm/mach/regs-rtc.h | 37 ++++
arch/unicore32/include/asm/mach/regs-sdc.h | 156 +++++++++++++++++
arch/unicore32/include/asm/mach/regs-spi.h | 98 +++++++++++
arch/unicore32/include/asm/mach/regs-uart.h | 3 +
arch/unicore32/include/asm/mach/regs-umal.h | 229 +++++++++++++++++++++++++
arch/unicore32/include/asm/mach/regs-unigfx.h | 200 +++++++++++++++++++++
20 files changed, 1615 insertions(+), 0 deletions(-)
diff --git a/arch/unicore32/include/asm/mach/PKUnity.h b/arch/unicore32/include/asm/mach/PKUnity.h
new file mode 100644
index 0000000..31cec2c
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/PKUnity.h
@@ -0,0 +1,104 @@
+/*
+ * linux/arch/unicore32/include/asm/mach/PKUnity.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+
+/* Be sure that virtual mapping is defined right */
+#ifndef __MACH_PUV3_HARDWARE_H__
+#error You must include hardware.h not PKUnity.h
+#endif
+
+#include "bitfield.h"
+
+/*
+ * Memory Definitions
+ */
+#define PKUNITY_SDRAM_BASE 0x00000000 /* 0x00000000 - 0x7FFFFFFF 2GB */
+#define PKUNITY_IOSPACE_BASE 0x80000000 /* 0x80000000 - 0xFFFFFFFF 2GB */
+#define PKUNITY_PCI_BASE 0x80000000 /* 0x80000000 - 0xBFFFFFFF 1GB */
+#include "regs-pci.h"
+#define PKUNITY_BOOT_ROM2_BASE 0xF4000000 /* 0xF4000000 - 0xF7FFFFFF 64MB */
+#define PKUNITY_BOOT_SRAM2_BASE 0xF8000000 /* 0xF8000000 - 0xFBFFFFFF 64MB */
+#define PKUNITY_BOOT_FLASH_BASE 0xFC000000 /* 0xFC000000 - 0xFFFFFFFF 64MB */
+
+/*
+ * PKUNITY Memory Map Addresses: 0x03000000 - 0x03FFFFFF (16MB)
+ */
+#define PKUNITY_UVC_MMAP_BASE 0x02000000 /* 0x02000000 - 0x02FFFFFF 16MB */
+#define PKUNITY_UVC_MMAP_SIZE 0x01000000 /* 16MB */
+#define PKUNITY_UNIGFX_MMAP_BASE 0x03000000 /* 0x03000000 - 0x03FFFFFF 16MB */
+#define PKUNITY_UNIGFX_MMAP_SIZE 0x01000000 /* 16MB */
+
+/*
+ * PKUNITY System Bus Addresses (PCI): 0x80000000 - 0xBFFFFFFF (1GB)
+ */
+/* PCI Configuration regs */
+#define PKUNITY_PCICFG_BASE 0x80000000 /* 0x80000000 - 0x8000000B 12B */
+/* PCI Bridge Base */
+#define PKUNITY_PCIBRI_BASE 0x80010000 /* 0x80010000 - 0x80010250 592B */
+/* PCI Legacy IO */
+#define PKUNITY_PCILIO_BASE 0x80030000 /* 0x80030000 - 0x8003FFFF 64KB */
+/* PCI AHB-PCI MEM-mapping */
+#define PKUNITY_PCIMEM_BASE 0x90000000 /* 0x90000000 - 0x97FFFFFF 128MB */
+/* PCI PCI-AHB MEM-mapping */
+#define PKUNITY_PCIAHB_BASE 0x98000000 /* 0x98000000 - 0x9FFFFFFF 128MB */
+
+/*
+ * PKUNITY System Bus Addresses (AHB): 0xC0000000 - 0xEDFFFFFF (640MB)
+ */
+/* AHB-0 is DDR2 SDRAM */
+/* AHB-1 is PCI Space */
+#define PKUNITY_ARBITER_BASE 0xC0000000 /* AHB-2 */
+#define PKUNITY_DDR2CTRL_BASE 0xC0100000 /* AHB-3 */
+#define PKUNITY_DMAC_BASE 0xC0200000 /* AHB-4 */
+#include "regs-dmac.h"
+#define PKUNITY_UMAL_BASE 0xC0300000 /* AHB-5 */
+#include "regs-umal.h"
+#define PKUNITY_USB_BASE 0xC0400000 /* AHB-6 */
+#define PKUNITY_SATA_BASE 0xC0500000 /* AHB-7 */
+#define PKUNITY_SMC_BASE 0xC0600000 /* AHB-8 */
+/* AHB-9 is for APB bridge */
+#define PKUNITY_MME_BASE 0xC0700000 /* AHB-10 */
+#define PKUNITY_UNIGFX_BASE 0xC0800000 /* AHB-11 */
+#include "regs-unigfx.h"
+#define PKUNITY_NAND_BASE 0xC0900000 /* AHB-12 */
+#include "regs-nand.h"
+#define PKUNITY_H264D_BASE 0xC0A00000 /* AHB-13 */
+#define PKUNITY_H264E_BASE 0xC0B00000 /* AHB-14 */
+
+/*
+ * PKUNITY Peripheral Bus Addresses (APB): 0xEE000000 - 0xEFFFFFFF (128MB)
+ */
+#define PKUNITY_UART0_BASE 0xEE000000 /* APB-0 */
+#define PKUNITY_UART1_BASE 0xEE100000 /* APB-1 */
+#include "regs-uart.h"
+#define PKUNITY_I2C_BASE 0xEE200000 /* APB-2 */
+#include "regs-i2c.h"
+#define PKUNITY_SPI_BASE 0xEE300000 /* APB-3 */
+#include "regs-spi.h"
+#define PKUNITY_AC97_BASE 0xEE400000 /* APB-4 */
+#include "regs-ac97.h"
+#define PKUNITY_GPIO_BASE 0xEE500000 /* APB-5 */
+#include "regs-gpio.h"
+#define PKUNITY_INTC_BASE 0xEE600000 /* APB-6 */
+#include "regs-intc.h"
+#define PKUNITY_RTC_BASE 0xEE700000 /* APB-7 */
+#include "regs-rtc.h"
+#define PKUNITY_OST_BASE 0xEE800000 /* APB-8 */
+#include "regs-ost.h"
+#define PKUNITY_RESETC_BASE 0xEE900000 /* APB-9 */
+#include "regs-resetc.h"
+#define PKUNITY_PM_BASE 0xEEA00000 /* APB-10 */
+#include "regs-pm.h"
+#define PKUNITY_PS2_BASE 0xEEB00000 /* APB-11 */
+#include "regs-ps2.h"
+#define PKUNITY_SDC_BASE 0xEEC00000 /* APB-12 */
+#include "regs-sdc.h"
+
diff --git a/arch/unicore32/include/asm/mach/bitfield.h b/arch/unicore32/include/asm/mach/bitfield.h
new file mode 100644
index 0000000..e038032
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/bitfield.h
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/unicore32/include/asm/mach/bitfield.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+#ifndef __MACH_PUV3_BITFIELD_H__
+#define __MACH_PUV3_BITFIELD_H__
+
+#ifndef __ASSEMBLY__
+#define UData(Data) ((unsigned long) (Data))
+#else
+#define UData(Data) (Data)
+#endif
+
+#define FIELD(val, vmask, vshift) (((val) & ((UData(1) << (vmask)) - 1)) << (vshift))
+#define FMASK(vmask, vshift) (((UData(1) << (vmask)) - 1) << (vshift))
+
+#endif /* __MACH_PUV3_BITFIELD_H__ */
diff --git a/arch/unicore32/include/asm/mach/hardware.h b/arch/unicore32/include/asm/mach/hardware.h
new file mode 100644
index 0000000..5a389fd
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/hardware.h
@@ -0,0 +1,45 @@
+/*
+ * linux/arch/unicore32/include/asm/mach/hardware.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ * This file contains the hardware definitions for PKUnity architecture
+ */
+
+#ifndef __MACH_PUV3_HARDWARE_H__
+#define __MACH_PUV3_HARDWARE_H__
+
+#include "PKUnity.h"
+
+#define io_p2v(x) ((x) - PKUNITY_IOSPACE_BASE)
+#define io_v2p(x) ((x) + PKUNITY_IOSPACE_BASE)
+
+#ifndef __ASSEMBLY__
+
+# define __REG(x) (*((volatile unsigned long *)io_p2v(x)))
+# define __PREG(x) (io_v2p((unsigned long)&(x)))
+
+#else
+
+# define __REG(x) io_p2v(x)
+# define __PREG(x) io_v2p(x)
+
+#endif
+
+#define PCIBIOS_MIN_IO 0x4000 /* should lower than 64KB */
+#define PCIBIOS_MIN_MEM PKUNITY_PCIMEM_BASE
+
+/*
+ * We override the standard dma-mask routines for bouncing.
+ */
+#define HAVE_ARCH_PCI_SET_DMA_MASK
+
+#define pcibios_assign_all_busses() 1
+
+#endif /* __MACH_PUV3_HARDWARE_H__ */
diff --git a/arch/unicore32/include/asm/mach/regs-ac97.h b/arch/unicore32/include/asm/mach/regs-ac97.h
new file mode 100644
index 0000000..ce299bf
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-ac97.h
@@ -0,0 +1,32 @@
+/*
+ * PKUnity AC97 Registers
+ */
+
+#define PKUNITY_AC97_CONR __REG(PKUNITY_AC97_BASE + 0x0000)
+#define PKUNITY_AC97_OCR __REG(PKUNITY_AC97_BASE + 0x0004)
+#define PKUNITY_AC97_ICR __REG(PKUNITY_AC97_BASE + 0x0008)
+#define PKUNITY_AC97_CRAC __REG(PKUNITY_AC97_BASE + 0x000C)
+#define PKUNITY_AC97_INTR __REG(PKUNITY_AC97_BASE + 0x0010)
+#define PKUNITY_AC97_INTRSTAT __REG(PKUNITY_AC97_BASE + 0x0014)
+#define PKUNITY_AC97_INTRCLEAR __REG(PKUNITY_AC97_BASE + 0x0018)
+#define PKUNITY_AC97_ENABLE __REG(PKUNITY_AC97_BASE + 0x001C)
+#define PKUNITY_AC97_OUT_FIFO __REG(PKUNITY_AC97_BASE + 0x0020)
+#define PKUNITY_AC97_IN_FIFO __REG(PKUNITY_AC97_BASE + 0x0030)
+
+#define AC97_CODEC_REG(v) FIELD((v), 7, 16)
+#define AC97_CODEC_VAL(v) FIELD((v), 16, 0)
+#define AC97_CODEC_WRITECOMPLETE FIELD(1, 1, 2)
+
+/*
+ * VAR PLAY SAMPLE RATE
+ */
+#define AC97_CMD_VPSAMPLE (FIELD(3, 2, 16) | FIELD(3, 2, 0))
+
+/*
+ * FIX CAPTURE SAMPLE RATE
+ */
+#define AC97_CMD_FCSAMPLE FIELD(7, 3, 0)
+
+#define AC97_CMD_RESET FIELD(1, 1, 0)
+#define AC97_CMD_ENABLE FIELD(1, 1, 0)
+#define AC97_CMD_DISABLE FIELD(0, 1, 0)
diff --git a/arch/unicore32/include/asm/mach/regs-dmac.h b/arch/unicore32/include/asm/mach/regs-dmac.h
new file mode 100644
index 0000000..09fce9d
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-dmac.h
@@ -0,0 +1,81 @@
+/*
+ * PKUnity Direct Memory Access Controller (DMAC)
+ */
+
+/*
+ * Interrupt Status Reg DMAC_ISR.
+ */
+#define DMAC_ISR __REG(PKUNITY_DMAC_BASE + 0x0020)
+/*
+ * Interrupt Transfer Complete Status Reg DMAC_ITCSR.
+ */
+#define DMAC_ITCSR __REG(PKUNITY_DMAC_BASE + 0x0050)
+/*
+ * Interrupt Transfer Complete Clear Reg DMAC_ITCCR.
+ */
+#define DMAC_ITCCR __REG(PKUNITY_DMAC_BASE + 0x0060)
+/*
+ * Interrupt Error Status Reg DMAC_IESR.
+ */
+#define DMAC_IESR __REG(PKUNITY_DMAC_BASE + 0x0080)
+/*
+ * Interrupt Error Clear Reg DMAC_IECR.
+ */
+#define DMAC_IECR __REG(PKUNITY_DMAC_BASE + 0x0090)
+/*
+ * Enable Channels Reg DMAC_ENCH.
+ */
+#define DMAC_ENCH __REG(PKUNITY_DMAC_BASE + 0x00B0)
+
+/*
+ * DMA control reg. Space [byte]
+ */
+#define DMASp 0x00000100
+
+/*
+ * Source Addr DMAC_SRCADDR(ch).
+ */
+#define DMAC_SRCADDR(ch) __REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x00)
+/*
+ * Destination Addr DMAC_DESTADDR(ch).
+ */
+#define DMAC_DESTADDR(ch) __REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x04)
+/*
+ * Control Reg DMAC_CONTROL(ch).
+ */
+#define DMAC_CONTROL(ch) __REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x0C)
+/*
+ * Configuration Reg DMAC_CONFIG(ch).
+ */
+#define DMAC_CONFIG(ch) __REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x10)
+
+#define DMAC_IR_MASK FMASK(6, 0)
+/*
+ * select channel (ch)
+ */
+#define DMAC_CHANNEL(ch) FIELD(1, 1, (ch))
+
+#define DMAC_CONTROL_SIZE_BYTE(v) (FIELD((v), 12, 14) | \
+ FIELD(0, 3, 9) | FIELD(0, 3, 6))
+#define DMAC_CONTROL_SIZE_HWORD(v) (FIELD((v) >> 1, 12, 14) | \
+ FIELD(1, 3, 9) | FIELD(1, 3, 6))
+#define DMAC_CONTROL_SIZE_WORD(v) (FIELD((v) >> 2, 12, 14) | \
+ FIELD(2, 3, 9) | FIELD(2, 3, 6))
+#define DMAC_CONTROL_DI FIELD(1, 1, 13)
+#define DMAC_CONTROL_SI FIELD(1, 1, 12)
+#define DMAC_CONTROL_BURST_1BYTE (FIELD(0, 3, 3) | FIELD(0, 3, 0))
+#define DMAC_CONTROL_BURST_4BYTE (FIELD(3, 3, 3) | FIELD(3, 3, 0))
+#define DMAC_CONTROL_BURST_8BYTE (FIELD(5, 3, 3) | FIELD(5, 3, 0))
+#define DMAC_CONTROL_BURST_16BYTE (FIELD(7, 3, 3) | FIELD(7, 3, 0))
+
+#define DMAC_CONFIG_UART0_WR (FIELD(2, 4, 11) | FIELD(1, 2, 1))
+#define DMAC_CONFIG_UART0_RD (FIELD(2, 4, 7) | FIELD(2, 2, 1))
+#define DMAC_CONFIG_UART1_WR (FIELD(3, 4, 11) | FIELD(1, 2, 1))
+#define DMAC_CONFIG_UART1RD (FIELD(3, 4, 7) | FIELD(2, 2, 1))
+#define DMAC_CONFIG_AC97WR (FIELD(4, 4, 11) | FIELD(1, 2, 1))
+#define DMAC_CONFIG_AC97RD (FIELD(4, 4, 7) | FIELD(2, 2, 1))
+#define DMAC_CONFIG_MMCWR (FIELD(7, 4, 11) | FIELD(1, 2, 1))
+#define DMAC_CONFIG_MMCRD (FIELD(7, 4, 7) | FIELD(2, 2, 1))
+#define DMAC_CONFIG_MASKITC FIELD(1, 1, 4)
+#define DMAC_CONFIG_MASKIE FIELD(1, 1, 3)
+#define DMAC_CONFIG_EN FIELD(1, 1, 0)
diff --git a/arch/unicore32/include/asm/mach/regs-gpio.h b/arch/unicore32/include/asm/mach/regs-gpio.h
new file mode 100644
index 0000000..5dd99d4
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-gpio.h
@@ -0,0 +1,70 @@
+/*
+ * PKUnity General-Purpose Input/Output (GPIO) Registers
+ */
+
+/*
+ * Voltage Status Reg GPIO_GPLR.
+ */
+#define GPIO_GPLR __REG(PKUNITY_GPIO_BASE + 0x0000)
+/*
+ * Pin Direction Reg GPIO_GPDR.
+ */
+#define GPIO_GPDR __REG(PKUNITY_GPIO_BASE + 0x0004)
+/*
+ * Output Pin Set Reg GPIO_GPSR.
+ */
+#define GPIO_GPSR __REG(PKUNITY_GPIO_BASE + 0x0008)
+/*
+ * Output Pin Clear Reg GPIO_GPCR.
+ */
+#define GPIO_GPCR __REG(PKUNITY_GPIO_BASE + 0x000C)
+/*
+ * Raise Edge Detect Reg GPIO_GRER.
+ */
+#define GPIO_GRER __REG(PKUNITY_GPIO_BASE + 0x0010)
+/*
+ * Fall Edge Detect Reg GPIO_GFER.
+ */
+#define GPIO_GFER __REG(PKUNITY_GPIO_BASE + 0x0014)
+/*
+ * Edge Status Reg GPIO_GEDR.
+ */
+#define GPIO_GEDR __REG(PKUNITY_GPIO_BASE + 0x0018)
+/*
+ * Sepcial Voltage Detect Reg GPIO_GPIR.
+ */
+#define GPIO_GPIR __REG(PKUNITY_GPIO_BASE + 0x0020)
+
+#define GPIO_MIN (0)
+#define GPIO_MAX (27)
+
+#define GPIO_GPIO(Nb) (0x00000001 << (Nb)) /* GPIO [0..27] */
+#define GPIO_GPIO0 GPIO_GPIO(0) /* GPIO [0] */
+#define GPIO_GPIO1 GPIO_GPIO(1) /* GPIO [1] */
+#define GPIO_GPIO2 GPIO_GPIO(2) /* GPIO [2] */
+#define GPIO_GPIO3 GPIO_GPIO(3) /* GPIO [3] */
+#define GPIO_GPIO4 GPIO_GPIO(4) /* GPIO [4] */
+#define GPIO_GPIO5 GPIO_GPIO(5) /* GPIO [5] */
+#define GPIO_GPIO6 GPIO_GPIO(6) /* GPIO [6] */
+#define GPIO_GPIO7 GPIO_GPIO(7) /* GPIO [7] */
+#define GPIO_GPIO8 GPIO_GPIO(8) /* GPIO [8] */
+#define GPIO_GPIO9 GPIO_GPIO(9) /* GPIO [9] */
+#define GPIO_GPIO10 GPIO_GPIO(10) /* GPIO [10] */
+#define GPIO_GPIO11 GPIO_GPIO(11) /* GPIO [11] */
+#define GPIO_GPIO12 GPIO_GPIO(12) /* GPIO [12] */
+#define GPIO_GPIO13 GPIO_GPIO(13) /* GPIO [13] */
+#define GPIO_GPIO14 GPIO_GPIO(14) /* GPIO [14] */
+#define GPIO_GPIO15 GPIO_GPIO(15) /* GPIO [15] */
+#define GPIO_GPIO16 GPIO_GPIO(16) /* GPIO [16] */
+#define GPIO_GPIO17 GPIO_GPIO(17) /* GPIO [17] */
+#define GPIO_GPIO18 GPIO_GPIO(18) /* GPIO [18] */
+#define GPIO_GPIO19 GPIO_GPIO(19) /* GPIO [19] */
+#define GPIO_GPIO20 GPIO_GPIO(20) /* GPIO [20] */
+#define GPIO_GPIO21 GPIO_GPIO(21) /* GPIO [21] */
+#define GPIO_GPIO22 GPIO_GPIO(22) /* GPIO [22] */
+#define GPIO_GPIO23 GPIO_GPIO(23) /* GPIO [23] */
+#define GPIO_GPIO24 GPIO_GPIO(24) /* GPIO [24] */
+#define GPIO_GPIO25 GPIO_GPIO(25) /* GPIO [25] */
+#define GPIO_GPIO26 GPIO_GPIO(26) /* GPIO [26] */
+#define GPIO_GPIO27 GPIO_GPIO(27) /* GPIO [27] */
+
diff --git a/arch/unicore32/include/asm/mach/regs-i2c.h b/arch/unicore32/include/asm/mach/regs-i2c.h
new file mode 100644
index 0000000..70b704f
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-i2c.h
@@ -0,0 +1,63 @@
+/*
+ * PKUnity Inter-integrated Circuit (I2C) Registers
+ */
+
+/*
+ * Control Reg I2C_CON.
+ */
+#define I2C_CON __REG(PKUNITY_I2C_BASE + 0x0000)
+/*
+ * Target Address Reg I2C_TAR.
+ */
+#define I2C_TAR __REG(PKUNITY_I2C_BASE + 0x0004)
+/*
+ * Data buffer and command Reg I2C_DATACMD.
+ */
+#define I2C_DATACMD __REG(PKUNITY_I2C_BASE + 0x0010)
+/*
+ * Enable Reg I2C_ENABLE.
+ */
+#define I2C_ENABLE __REG(PKUNITY_I2C_BASE + 0x006C)
+/*
+ * Status Reg I2C_STATUS.
+ */
+#define I2C_STATUS __REG(PKUNITY_I2C_BASE + 0x0070)
+/*
+ * Tx FIFO Length Reg I2C_TXFLR.
+ */
+#define I2C_TXFLR __REG(PKUNITY_I2C_BASE + 0x0074)
+/*
+ * Rx FIFO Length Reg I2C_RXFLR.
+ */
+#define I2C_RXFLR __REG(PKUNITY_I2C_BASE + 0x0078)
+/*
+ * Enable Status Reg I2C_ENSTATUS.
+ */
+#define I2C_ENSTATUS __REG(PKUNITY_I2C_BASE + 0x009C)
+
+#define I2C_CON_MASTER FIELD(1, 1, 0)
+#define I2C_CON_SPEED_STD FIELD(1, 2, 1)
+#define I2C_CON_SPEED_FAST FIELD(2, 2, 1)
+#define I2C_CON_RESTART FIELD(1, 1, 5)
+#define I2C_CON_SLAVEDISABLE FIELD(1, 1, 6)
+
+#define I2C_DATACMD_READ FIELD(1, 1, 8)
+#define I2C_DATACMD_WRITE FIELD(0, 1, 8)
+#define I2C_DATACMD_DAT_MASK FMASK(8, 0)
+#define I2C_DATACMD_DAT(v) FIELD((v), 8, 0)
+
+#define I2C_ENABLE_ENABLE FIELD(1, 1, 0)
+#define I2C_ENABLE_DISABLE FIELD(0, 1, 0)
+
+#define I2C_STATUS_RFF FIELD(1, 1, 4)
+#define I2C_STATUS_RFNE FIELD(1, 1, 3)
+#define I2C_STATUS_TFE FIELD(1, 1, 2)
+#define I2C_STATUS_TFNF FIELD(1, 1, 1)
+#define I2C_STATUS_ACTIVITY FIELD(1, 1, 0)
+
+#define I2C_ENSTATUS_ENABLE FIELD(1, 1, 0)
+
+#define I2C_TAR_THERMAL 0x4f
+#define I2C_TAR_SPD 0x50
+#define I2C_TAR_PWIC 0x55
+#define I2C_TAR_EEPROM 0x57
diff --git a/arch/unicore32/include/asm/mach/regs-intc.h b/arch/unicore32/include/asm/mach/regs-intc.h
new file mode 100644
index 0000000..409ae47
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-intc.h
@@ -0,0 +1,28 @@
+/*
+ * PKUNITY Interrupt Controller (INTC) Registers
+ */
+/*
+ * INTC Level Reg INTC_ICLR.
+ */
+#define INTC_ICLR __REG(PKUNITY_INTC_BASE + 0x0000)
+/*
+ * INTC Mask Reg INTC_ICMR.
+ */
+#define INTC_ICMR __REG(PKUNITY_INTC_BASE + 0x0004)
+/*
+ * INTC Pending Reg INTC_ICPR.
+ */
+#define INTC_ICPR __REG(PKUNITY_INTC_BASE + 0x0008)
+/*
+ * INTC IRQ Pending Reg INTC_ICIP.
+ */
+#define INTC_ICIP __REG(PKUNITY_INTC_BASE + 0x000C)
+/*
+ * INTC REAL Pending Reg INTC_ICFP.
+ */
+#define INTC_ICFP __REG(PKUNITY_INTC_BASE + 0x0010)
+/*
+ * INTC Control Reg INTC_ICCR.
+ */
+#define INTC_ICCR __REG(PKUNITY_INTC_BASE + 0x0014)
+
diff --git a/arch/unicore32/include/asm/mach/regs-nand.h b/arch/unicore32/include/asm/mach/regs-nand.h
new file mode 100644
index 0000000..0c33fe8
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-nand.h
@@ -0,0 +1,79 @@
+/*
+ * PKUnity NAND Controller Registers
+ */
+/*
+ * ID Reg. 0 NAND_IDR0
+ */
+#define NAND_IDR0 __REG(PKUNITY_NAND_BASE + 0x0000)
+/*
+ * ID Reg. 1 NAND_IDR1
+ */
+#define NAND_IDR1 __REG(PKUNITY_NAND_BASE + 0x0004)
+/*
+ * ID Reg. 2 NAND_IDR2
+ */
+#define NAND_IDR2 __REG(PKUNITY_NAND_BASE + 0x0008)
+/*
+ * ID Reg. 3 NAND_IDR3
+ */
+#define NAND_IDR3 __REG(PKUNITY_NAND_BASE + 0x000C)
+/*
+ * Page Address Reg 0 NAND_PAR0
+ */
+#define NAND_PAR0 __REG(PKUNITY_NAND_BASE + 0x0010)
+/*
+ * Page Address Reg 1 NAND_PAR1
+ */
+#define NAND_PAR1 __REG(PKUNITY_NAND_BASE + 0x0014)
+/*
+ * Page Address Reg 2 NAND_PAR2
+ */
+#define NAND_PAR2 __REG(PKUNITY_NAND_BASE + 0x0018)
+/*
+ * ECC Enable Reg NAND_ECCEN
+ */
+#define NAND_ECCEN __REG(PKUNITY_NAND_BASE + 0x001C)
+/*
+ * Buffer Reg NAND_BUF
+ */
+#define NAND_BUF __REG(PKUNITY_NAND_BASE + 0x0020)
+/*
+ * ECC Status Reg NAND_ECCSR
+ */
+#define NAND_ECCSR __REG(PKUNITY_NAND_BASE + 0x0024)
+/*
+ * Command Reg NAND_CMD
+ */
+#define NAND_CMD __REG(PKUNITY_NAND_BASE + 0x0028)
+/*
+ * DMA Configure Reg NAND_DMACR
+ */
+#define NAND_DMACR __REG(PKUNITY_NAND_BASE + 0x002C)
+/*
+ * Interrupt Reg NAND_IR
+ */
+#define NAND_IR __REG(PKUNITY_NAND_BASE + 0x0030)
+/*
+ * Interrupt Mask Reg NAND_IMR
+ */
+#define NAND_IMR __REG(PKUNITY_NAND_BASE + 0x0034)
+/*
+ * Chip Enable Reg NAND_CHIPEN
+ */
+#define NAND_CHIPEN __REG(PKUNITY_NAND_BASE + 0x0038)
+/*
+ * Address Reg NAND_ADDR
+ */
+#define NAND_ADDR __REG(PKUNITY_NAND_BASE + 0x003C)
+
+/*
+ * Command bits NAND_CMD_CMD_MASK
+ */
+#define NAND_CMD_CMD_MASK FMASK(4, 4)
+#define NAND_CMD_CMD_READPAGE FIELD(0x0, 4, 4)
+#define NAND_CMD_CMD_ERASEBLOCK FIELD(0x6, 4, 4)
+#define NAND_CMD_CMD_READSTATUS FIELD(0x7, 4, 4)
+#define NAND_CMD_CMD_WRITEPAGE FIELD(0x8, 4, 4)
+#define NAND_CMD_CMD_READID FIELD(0x9, 4, 4)
+#define NAND_CMD_CMD_RESET FIELD(0xf, 4, 4)
+
diff --git a/arch/unicore32/include/asm/mach/regs-ost.h b/arch/unicore32/include/asm/mach/regs-ost.h
new file mode 100644
index 0000000..33049a8
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-ost.h
@@ -0,0 +1,92 @@
+/*
+ * PKUnity Operating System Timer (OST) Registers
+ */
+/*
+ * Match Reg 0 OST_OSMR0
+ */
+#define OST_OSMR0 __REG(PKUNITY_OST_BASE + 0x0000)
+/*
+ * Match Reg 1 OST_OSMR1
+ */
+#define OST_OSMR1 __REG(PKUNITY_OST_BASE + 0x0004)
+/*
+ * Match Reg 2 OST_OSMR2
+ */
+#define OST_OSMR2 __REG(PKUNITY_OST_BASE + 0x0008)
+/*
+ * Match Reg 3 OST_OSMR3
+ */
+#define OST_OSMR3 __REG(PKUNITY_OST_BASE + 0x000C)
+/*
+ * Counter Reg OST_OSCR
+ */
+#define OST_OSCR __REG(PKUNITY_OST_BASE + 0x0010)
+/*
+ * Status Reg OST_OSSR
+ */
+#define OST_OSSR __REG(PKUNITY_OST_BASE + 0x0014)
+/*
+ * Watchdog Enable Reg OST_OWER
+ */
+#define OST_OWER __REG(PKUNITY_OST_BASE + 0x0018)
+/*
+ * Interrupt Enable Reg OST_OIER
+ */
+#define OST_OIER __REG(PKUNITY_OST_BASE + 0x001C)
+/*
+ * PWM Pulse Width Control Reg OST_PWMPWCR
+ */
+#define OST_PWMPWCR __REG(PKUNITY_OST_BASE + 0x0080)
+/*
+ * PWM Duty Cycle Control Reg OST_PWMDCCR
+ */
+#define OST_PWMDCCR __REG(PKUNITY_OST_BASE + 0x0084)
+/*
+ * PWM Period Control Reg OST_PWMPCR
+ */
+#define OST_PWMPCR __REG(PKUNITY_OST_BASE + 0x0088)
+
+/*
+ * Match detected 0 OST_OSSR_M0
+ */
+#define OST_OSSR_M0 FIELD(1, 1, 0)
+/*
+ * Match detected 1 OST_OSSR_M1
+ */
+#define OST_OSSR_M1 FIELD(1, 1, 1)
+/*
+ * Match detected 2 OST_OSSR_M2
+ */
+#define OST_OSSR_M2 FIELD(1, 1, 2)
+/*
+ * Match detected 3 OST_OSSR_M3
+ */
+#define OST_OSSR_M3 FIELD(1, 1, 3)
+
+/*
+ * Interrupt enable 0 OST_OIER_E0
+ */
+#define OST_OIER_E0 FIELD(1, 1, 0)
+/*
+ * Interrupt enable 1 OST_OIER_E1
+ */
+#define OST_OIER_E1 FIELD(1, 1, 1)
+/*
+ * Interrupt enable 2 OST_OIER_E2
+ */
+#define OST_OIER_E2 FIELD(1, 1, 2)
+/*
+ * Interrupt enable 3 OST_OIER_E3
+ */
+#define OST_OIER_E3 FIELD(1, 1, 3)
+
+/*
+ * Watchdog Match Enable OST_OWER_WME
+ */
+#define OST_OWER_WME FIELD(1, 1, 0)
+
+/*
+ * PWM Full Duty Cycle OST_PWMDCCR_FDCYCLE
+ */
+#define OST_PWMDCCR_FDCYCLE FIELD(1, 1, 10)
+
diff --git a/arch/unicore32/include/asm/mach/regs-pci.h b/arch/unicore32/include/asm/mach/regs-pci.h
new file mode 100644
index 0000000..e8e1f1a
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-pci.h
@@ -0,0 +1,94 @@
+/*
+ * PKUnity AHB-PCI Bridge Registers
+ */
+
+/*
+ * AHB/PCI fixed physical address for pci addess configuration
+ */
+/*
+ * PCICFG Bridge Base Reg.
+ */
+#define PCICFG_BRIBASE __REG(PKUNITY_PCICFG_BASE + 0x0000)
+/*
+ * PCICFG Address Reg.
+ */
+#define PCICFG_ADDR __REG(PKUNITY_PCICFG_BASE + 0x0004)
+/*
+ * PCICFG Address Reg.
+ */
+#define PCICFG_DATA __REG(PKUNITY_PCICFG_BASE + 0x0008)
+
+/*
+ * PCI Bridge configuration space
+ */
+#define PCIBRI_ID __REG(PKUNITY_PCIBRI_BASE + 0x0000)
+#define PCIBRI_CMD __REG(PKUNITY_PCIBRI_BASE + 0x0004)
+#define PCIBRI_CLASS __REG(PKUNITY_PCIBRI_BASE + 0x0008)
+#define PCIBRI_LTR __REG(PKUNITY_PCIBRI_BASE + 0x000C)
+#define PCIBRI_BAR0 __REG(PKUNITY_PCIBRI_BASE + 0x0010)
+#define PCIBRI_BAR1 __REG(PKUNITY_PCIBRI_BASE + 0x0014)
+#define PCIBRI_BAR2 __REG(PKUNITY_PCIBRI_BASE + 0x0018)
+#define PCIBRI_BAR3 __REG(PKUNITY_PCIBRI_BASE + 0x001C)
+#define PCIBRI_BAR4 __REG(PKUNITY_PCIBRI_BASE + 0x0020)
+#define PCIBRI_BAR5 __REG(PKUNITY_PCIBRI_BASE + 0x0024)
+
+#define PCIBRI_PCICTL0 __REG(PKUNITY_PCIBRI_BASE + 0x0100)
+#define PCIBRI_PCIBAR0 __REG(PKUNITY_PCIBRI_BASE + 0x0104)
+#define PCIBRI_PCIAMR0 __REG(PKUNITY_PCIBRI_BASE + 0x0108)
+#define PCIBRI_PCITAR0 __REG(PKUNITY_PCIBRI_BASE + 0x010C)
+#define PCIBRI_PCICTL1 __REG(PKUNITY_PCIBRI_BASE + 0x0110)
+#define PCIBRI_PCIBAR1 __REG(PKUNITY_PCIBRI_BASE + 0x0114)
+#define PCIBRI_PCIAMR1 __REG(PKUNITY_PCIBRI_BASE + 0x0118)
+#define PCIBRI_PCITAR1 __REG(PKUNITY_PCIBRI_BASE + 0x011C)
+#define PCIBRI_PCICTL2 __REG(PKUNITY_PCIBRI_BASE + 0x0120)
+#define PCIBRI_PCIBAR2 __REG(PKUNITY_PCIBRI_BASE + 0x0124)
+#define PCIBRI_PCIAMR2 __REG(PKUNITY_PCIBRI_BASE + 0x0128)
+#define PCIBRI_PCITAR2 __REG(PKUNITY_PCIBRI_BASE + 0x012C)
+#define PCIBRI_PCICTL3 __REG(PKUNITY_PCIBRI_BASE + 0x0130)
+#define PCIBRI_PCIBAR3 __REG(PKUNITY_PCIBRI_BASE + 0x0134)
+#define PCIBRI_PCIAMR3 __REG(PKUNITY_PCIBRI_BASE + 0x0138)
+#define PCIBRI_PCITAR3 __REG(PKUNITY_PCIBRI_BASE + 0x013C)
+#define PCIBRI_PCICTL4 __REG(PKUNITY_PCIBRI_BASE + 0x0140)
+#define PCIBRI_PCIBAR4 __REG(PKUNITY_PCIBRI_BASE + 0x0144)
+#define PCIBRI_PCIAMR4 __REG(PKUNITY_PCIBRI_BASE + 0x0148)
+#define PCIBRI_PCITAR4 __REG(PKUNITY_PCIBRI_BASE + 0x014C)
+#define PCIBRI_PCICTL5 __REG(PKUNITY_PCIBRI_BASE + 0x0150)
+#define PCIBRI_PCIBAR5 __REG(PKUNITY_PCIBRI_BASE + 0x0154)
+#define PCIBRI_PCIAMR5 __REG(PKUNITY_PCIBRI_BASE + 0x0158)
+#define PCIBRI_PCITAR5 __REG(PKUNITY_PCIBRI_BASE + 0x015C)
+
+#define PCIBRI_AHBCTL0 __REG(PKUNITY_PCIBRI_BASE + 0x0180)
+#define PCIBRI_AHBBAR0 __REG(PKUNITY_PCIBRI_BASE + 0x0184)
+#define PCIBRI_AHBAMR0 __REG(PKUNITY_PCIBRI_BASE + 0x0188)
+#define PCIBRI_AHBTAR0 __REG(PKUNITY_PCIBRI_BASE + 0x018C)
+#define PCIBRI_AHBCTL1 __REG(PKUNITY_PCIBRI_BASE + 0x0190)
+#define PCIBRI_AHBBAR1 __REG(PKUNITY_PCIBRI_BASE + 0x0194)
+#define PCIBRI_AHBAMR1 __REG(PKUNITY_PCIBRI_BASE + 0x0198)
+#define PCIBRI_AHBTAR1 __REG(PKUNITY_PCIBRI_BASE + 0x019C)
+#define PCIBRI_AHBCTL2 __REG(PKUNITY_PCIBRI_BASE + 0x01A0)
+#define PCIBRI_AHBBAR2 __REG(PKUNITY_PCIBRI_BASE + 0x01A4)
+#define PCIBRI_AHBAMR2 __REG(PKUNITY_PCIBRI_BASE + 0x01A8)
+#define PCIBRI_AHBTAR2 __REG(PKUNITY_PCIBRI_BASE + 0x01AC)
+#define PCIBRI_AHBCTL3 __REG(PKUNITY_PCIBRI_BASE + 0x01B0)
+#define PCIBRI_AHBBAR3 __REG(PKUNITY_PCIBRI_BASE + 0x01B4)
+#define PCIBRI_AHBAMR3 __REG(PKUNITY_PCIBRI_BASE + 0x01B8)
+#define PCIBRI_AHBTAR3 __REG(PKUNITY_PCIBRI_BASE + 0x01BC)
+#define PCIBRI_AHBCTL4 __REG(PKUNITY_PCIBRI_BASE + 0x01C0)
+#define PCIBRI_AHBBAR4 __REG(PKUNITY_PCIBRI_BASE + 0x01C4)
+#define PCIBRI_AHBAMR4 __REG(PKUNITY_PCIBRI_BASE + 0x01C8)
+#define PCIBRI_AHBTAR4 __REG(PKUNITY_PCIBRI_BASE + 0x01CC)
+#define PCIBRI_AHBCTL5 __REG(PKUNITY_PCIBRI_BASE + 0x01D0)
+#define PCIBRI_AHBBAR5 __REG(PKUNITY_PCIBRI_BASE + 0x01D4)
+#define PCIBRI_AHBAMR5 __REG(PKUNITY_PCIBRI_BASE + 0x01D8)
+#define PCIBRI_AHBTAR5 __REG(PKUNITY_PCIBRI_BASE + 0x01DC)
+
+#define PCIBRI_CTLx_AT FIELD(1, 1, 2)
+#define PCIBRI_CTLx_PREF FIELD(1, 1, 1)
+#define PCIBRI_CTLx_MRL FIELD(1, 1, 0)
+
+#define PCIBRI_BARx_ADDR FIELD(0xFFFFFFFC, 30, 2)
+#define PCIBRI_BARx_IO FIELD(1, 1, 0)
+#define PCIBRI_BARx_MEM FIELD(0, 1, 0)
+
+#define PCIBRI_CMD_IO FIELD(1, 1, 0)
+#define PCIBRI_CMD_MEM FIELD(1, 1, 1)
diff --git a/arch/unicore32/include/asm/mach/regs-pm.h b/arch/unicore32/include/asm/mach/regs-pm.h
new file mode 100644
index 0000000..ed2d2fc
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-pm.h
@@ -0,0 +1,126 @@
+/*
+ * PKUNITY Power Manager (PM) Registers
+ */
+/*
+ * PM Control Reg PM_PMCR
+ */
+#define PM_PMCR __REG(PKUNITY_PM_BASE + 0x0000)
+/*
+ * PM General Conf. Reg PM_PGCR
+ */
+#define PM_PGCR __REG(PKUNITY_PM_BASE + 0x0004)
+/*
+ * PM PLL Conf. Reg PM_PPCR
+ */
+#define PM_PPCR __REG(PKUNITY_PM_BASE + 0x0008)
+/*
+ * PM Wakeup Enable Reg PM_PWER
+ */
+#define PM_PWER __REG(PKUNITY_PM_BASE + 0x000C)
+/*
+ * PM GPIO Sleep Status Reg PM_PGSR
+ */
+#define PM_PGSR __REG(PKUNITY_PM_BASE + 0x0010)
+/*
+ * PM Clock Gate Reg PM_PCGR
+ */
+#define PM_PCGR __REG(PKUNITY_PM_BASE + 0x0014)
+/*
+ * PM SYS PLL Conf. Reg PM_PLLSYSCFG
+ */
+#define PM_PLLSYSCFG __REG(PKUNITY_PM_BASE + 0x0018)
+/*
+ * PM DDR PLL Conf. Reg PM_PLLDDRCFG
+ */
+#define PM_PLLDDRCFG __REG(PKUNITY_PM_BASE + 0x001C)
+/*
+ * PM VGA PLL Conf. Reg PM_PLLVGACFG
+ */
+#define PM_PLLVGACFG __REG(PKUNITY_PM_BASE + 0x0020)
+/*
+ * PM Div Conf. Reg PM_DIVCFG
+ */
+#define PM_DIVCFG __REG(PKUNITY_PM_BASE + 0x0024)
+/*
+ * PM SYS PLL Status Reg PM_PLLSYSSTATUS
+ */
+#define PM_PLLSYSSTATUS __REG(PKUNITY_PM_BASE + 0x0028)
+/*
+ * PM DDR PLL Status Reg PM_PLLDDRSTATUS
+ */
+#define PM_PLLDDRSTATUS __REG(PKUNITY_PM_BASE + 0x002C)
+/*
+ * PM VGA PLL Status Reg PM_PLLVGASTATUS
+ */
+#define PM_PLLVGASTATUS __REG(PKUNITY_PM_BASE + 0x0030)
+/*
+ * PM Div Status Reg PM_DIVSTATUS
+ */
+#define PM_DIVSTATUS __REG(PKUNITY_PM_BASE + 0x0034)
+/*
+ * PM Software Reset Reg PM_SWRESET
+ */
+#define PM_SWRESET __REG(PKUNITY_PM_BASE + 0x0038)
+/*
+ * PM DDR2 PAD Start Reg PM_DDR2START
+ */
+#define PM_DDR2START __REG(PKUNITY_PM_BASE + 0x003C)
+/*
+ * PM DDR2 PAD Status Reg PM_DDR2CAL0
+ */
+#define PM_DDR2CAL0 __REG(PKUNITY_PM_BASE + 0x0040)
+/*
+ * PM PLL DFC Done Reg PM_PLLDFCDONE
+ */
+#define PM_PLLDFCDONE __REG(PKUNITY_PM_BASE + 0x0044)
+
+#define PM_PMCR_SFB FIELD(1, 1, 0)
+#define PM_PMCR_IFB FIELD(1, 1, 1)
+#define PM_PMCR_CFBSYS FIELD(1, 1, 2)
+#define PM_PMCR_CFBDDR FIELD(1, 1, 3)
+#define PM_PMCR_CFBVGA FIELD(1, 1, 4)
+#define PM_PMCR_CFBDIVBCLK FIELD(1, 1, 5)
+
+/*
+ * GPIO 8~27 wake-up enable PM_PWER_GPIOHIGH
+ */
+#define PM_PWER_GPIOHIGH FIELD(1, 1, 8)
+/*
+ * RTC alarm wake-up enable PM_PWER_RTC
+ */
+#define PM_PWER_RTC FIELD(1, 1, 31)
+
+#define PM_PCGR_BCLK64DDR FIELD(1, 1, 0)
+#define PM_PCGR_BCLK64VGA FIELD(1, 1, 1)
+#define PM_PCGR_BCLKDDR FIELD(1, 1, 2)
+#define PM_PCGR_BCLKPCI FIELD(1, 1, 4)
+#define PM_PCGR_BCLKDMAC FIELD(1, 1, 5)
+#define PM_PCGR_BCLKUMAL FIELD(1, 1, 6)
+#define PM_PCGR_BCLKUSB FIELD(1, 1, 7)
+#define PM_PCGR_BCLKMME FIELD(1, 1, 10)
+#define PM_PCGR_BCLKNAND FIELD(1, 1, 11)
+#define PM_PCGR_BCLKH264E FIELD(1, 1, 12)
+#define PM_PCGR_BCLKVGA FIELD(1, 1, 13)
+#define PM_PCGR_BCLKH264D FIELD(1, 1, 14)
+#define PM_PCGR_VECLK FIELD(1, 1, 15)
+#define PM_PCGR_HECLK FIELD(1, 1, 16)
+#define PM_PCGR_HDCLK FIELD(1, 1, 17)
+#define PM_PCGR_NANDCLK FIELD(1, 1, 18)
+#define PM_PCGR_GECLK FIELD(1, 1, 19)
+#define PM_PCGR_VGACLK FIELD(1, 1, 20)
+#define PM_PCGR_PCICLK FIELD(1, 1, 21)
+#define PM_PCGR_SATACLK FIELD(1, 1, 25)
+
+/*
+ * [23:20]PM_DIVCFG_VGACLK(v)
+ */
+#define PM_DIVCFG_VGACLK_MASK FMASK(4, 20)
+#define PM_DIVCFG_VGACLK(v) FIELD((v), 4, 20)
+
+#define PM_SWRESET_USB FIELD(1, 1, 6)
+#define PM_SWRESET_VGADIV FIELD(1, 1, 26)
+#define PM_SWRESET_GEDIV FIELD(1, 1, 27)
+
+#define PM_PLLDFCDONE_SYSDFC FIELD(1, 1, 0)
+#define PM_PLLDFCDONE_DDRDFC FIELD(1, 1, 1)
+#define PM_PLLDFCDONE_VGADFC FIELD(1, 1, 2)
diff --git a/arch/unicore32/include/asm/mach/regs-ps2.h b/arch/unicore32/include/asm/mach/regs-ps2.h
new file mode 100644
index 0000000..7da2071
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-ps2.h
@@ -0,0 +1,20 @@
+/*
+ * PKUnity PS2 Controller Registers
+ */
+/*
+ * the same as I8042_DATA_REG PS2_DATA
+ */
+#define PS2_DATA __REG(PKUNITY_PS2_BASE + 0x0060)
+/*
+ * the same as I8042_COMMAND_REG PS2_COMMAND
+ */
+#define PS2_COMMAND __REG(PKUNITY_PS2_BASE + 0x0064)
+/*
+ * the same as I8042_STATUS_REG PS2_STATUS
+ */
+#define PS2_STATUS __REG(PKUNITY_PS2_BASE + 0x0064)
+/*
+ * counter reg PS2_CNT
+ */
+#define PS2_CNT __REG(PKUNITY_PS2_BASE + 0x0068)
+
diff --git a/arch/unicore32/include/asm/mach/regs-resetc.h b/arch/unicore32/include/asm/mach/regs-resetc.h
new file mode 100644
index 0000000..1763989
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-resetc.h
@@ -0,0 +1,34 @@
+/*
+ * PKUnity Reset Controller (RC) Registers
+ */
+/*
+ * Software Reset Register
+ */
+#define RESETC_SWRR __REG(PKUNITY_RESETC_BASE + 0x0000)
+/*
+ * Reset Status Register
+ */
+#define RESETC_RSSR __REG(PKUNITY_RESETC_BASE + 0x0004)
+
+/*
+ * Software Reset Bit
+ */
+#define RESETC_SWRR_SRB FIELD(1, 1, 0)
+
+/*
+ * Hardware Reset
+ */
+#define RESETC_RSSR_HWR FIELD(1, 1, 0)
+/*
+ * Software Reset
+ */
+#define RESETC_RSSR_SWR FIELD(1, 1, 1)
+/*
+ * Watchdog Reset
+ */
+#define RESETC_RSSR_WDR FIELD(1, 1, 2)
+/*
+ * Sleep Mode Reset
+ */
+#define RESETC_RSSR_SMR FIELD(1, 1, 3)
+
diff --git a/arch/unicore32/include/asm/mach/regs-rtc.h b/arch/unicore32/include/asm/mach/regs-rtc.h
new file mode 100644
index 0000000..155e387
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-rtc.h
@@ -0,0 +1,37 @@
+/*
+ * PKUnity Real-Time Clock (RTC) control registers
+ */
+/*
+ * RTC Alarm Reg RTC_RTAR
+ */
+#define RTC_RTAR __REG(PKUNITY_RTC_BASE + 0x0000)
+/*
+ * RTC Count Reg RTC_RCNR
+ */
+#define RTC_RCNR __REG(PKUNITY_RTC_BASE + 0x0004)
+/*
+ * RTC Trim Reg RTC_RTTR
+ */
+#define RTC_RTTR __REG(PKUNITY_RTC_BASE + 0x0008)
+/*
+ * RTC Status Reg RTC_RTSR
+ */
+#define RTC_RTSR __REG(PKUNITY_RTC_BASE + 0x0010)
+
+/*
+ * ALarm detected RTC_RTSR_AL
+ */
+#define RTC_RTSR_AL FIELD(1, 1, 0)
+/*
+ * 1 Hz clock detected RTC_RTSR_HZ
+ */
+#define RTC_RTSR_HZ FIELD(1, 1, 1)
+/*
+ * ALarm interrupt Enable RTC_RTSR_ALE
+ */
+#define RTC_RTSR_ALE FIELD(1, 1, 2)
+/*
+ * 1 Hz clock interrupt Enable RTC_RTSR_HZE
+ */
+#define RTC_RTSR_HZE FIELD(1, 1, 3)
+
diff --git a/arch/unicore32/include/asm/mach/regs-sdc.h b/arch/unicore32/include/asm/mach/regs-sdc.h
new file mode 100644
index 0000000..3457b88
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-sdc.h
@@ -0,0 +1,156 @@
+/*
+ * PKUnity Multi-Media Card and Security Digital Card (MMC/SD) Registers
+ */
+/*
+ * Clock Control Reg SDC_CCR
+ */
+#define SDC_CCR __REG(PKUNITY_SDC_BASE + 0x0000)
+/*
+ * Software Reset Reg SDC_SRR
+ */
+#define SDC_SRR __REG(PKUNITY_SDC_BASE + 0x0004)
+/*
+ * Argument Reg SDC_ARGUMENT
+ */
+#define SDC_ARGUMENT __REG(PKUNITY_SDC_BASE + 0x0008)
+/*
+ * Command Reg SDC_COMMAND
+ */
+#define SDC_COMMAND __REG(PKUNITY_SDC_BASE + 0x000C)
+/*
+ * Block Size Reg SDC_BLOCKSIZE
+ */
+#define SDC_BLOCKSIZE __REG(PKUNITY_SDC_BASE + 0x0010)
+/*
+ * Block Cound Reg SDC_BLOCKCOUNT
+ */
+#define SDC_BLOCKCOUNT __REG(PKUNITY_SDC_BASE + 0x0014)
+/*
+ * Transfer Mode Reg SDC_TMR
+ */
+#define SDC_TMR __REG(PKUNITY_SDC_BASE + 0x0018)
+/*
+ * Response Reg. 0 SDC_RES0
+ */
+#define SDC_RES0 __REG(PKUNITY_SDC_BASE + 0x001C)
+/*
+ * Response Reg. 1 SDC_RES1
+ */
+#define SDC_RES1 __REG(PKUNITY_SDC_BASE + 0x0020)
+/*
+ * Response Reg. 2 SDC_RES2
+ */
+#define SDC_RES2 __REG(PKUNITY_SDC_BASE + 0x0024)
+/*
+ * Response Reg. 3 SDC_RES3
+ */
+#define SDC_RES3 __REG(PKUNITY_SDC_BASE + 0x0028)
+/*
+ * Read Timeout Control Reg SDC_RTCR
+ */
+#define SDC_RTCR __REG(PKUNITY_SDC_BASE + 0x002C)
+/*
+ * Interrupt Status Reg SDC_ISR
+ */
+#define SDC_ISR __REG(PKUNITY_SDC_BASE + 0x0030)
+/*
+ * Interrupt Status Mask Reg SDC_ISMR
+ */
+#define SDC_ISMR __REG(PKUNITY_SDC_BASE + 0x0034)
+/*
+ * RX FIFO SDC_RXFIFO
+ */
+#define SDC_RXFIFO __REG(PKUNITY_SDC_BASE + 0x0038)
+/*
+ * TX FIFO SDC_TXFIFO
+ */
+#define SDC_TXFIFO __REG(PKUNITY_SDC_BASE + 0x003C)
+
+/*
+ * SD Clock Enable SDC_CCR_CLKEN
+ */
+#define SDC_CCR_CLKEN FIELD(1, 1, 2)
+/*
+ * [15:8] SDC_CCR_PDIV(v)
+ */
+#define SDC_CCR_PDIV(v) FIELD((v), 8, 8)
+
+/*
+ * Software reset enable SDC_SRR_ENABLE
+ */
+#define SDC_SRR_ENABLE FIELD(0, 1, 0)
+/*
+ * Software reset disable SDC_SRR_DISABLE
+ */
+#define SDC_SRR_DISABLE FIELD(1, 1, 0)
+
+/*
+ * Response type SDC_COMMAND_RESTYPE_MASK
+ */
+#define SDC_COMMAND_RESTYPE_MASK FMASK(2, 0)
+/*
+ * No response SDC_COMMAND_RESTYPE_NONE
+ */
+#define SDC_COMMAND_RESTYPE_NONE FIELD(0, 2, 0)
+/*
+ * 136-bit long response SDC_COMMAND_RESTYPE_LONG
+ */
+#define SDC_COMMAND_RESTYPE_LONG FIELD(1, 2, 0)
+/*
+ * 48-bit short response SDC_COMMAND_RESTYPE_SHORT
+ */
+#define SDC_COMMAND_RESTYPE_SHORT FIELD(2, 2, 0)
+/*
+ * 48-bit short and test if busy response SDC_COMMAND_RESTYPE_SHORTBUSY
+ */
+#define SDC_COMMAND_RESTYPE_SHORTBUSY FIELD(3, 2, 0)
+/*
+ * data ready SDC_COMMAND_DATAREADY
+ */
+#define SDC_COMMAND_DATAREADY FIELD(1, 1, 2)
+#define SDC_COMMAND_CMDEN FIELD(1, 1, 3)
+/*
+ * [10:5] SDC_COMMAND_CMDINDEX(v)
+ */
+#define SDC_COMMAND_CMDINDEX(v) FIELD((v), 6, 5)
+
+/*
+ * [10:0] SDC_BLOCKSIZE_BSMASK(v)
+ */
+#define SDC_BLOCKSIZE_BSMASK(v) FIELD((v), 11, 0)
+/*
+ * [11:0] SDC_BLOCKCOUNT_BCMASK(v)
+ */
+#define SDC_BLOCKCOUNT_BCMASK(v) FIELD((v), 12, 0)
+
+/*
+ * Data Width 1bit SDC_TMR_WTH_1BIT
+ */
+#define SDC_TMR_WTH_1BIT FIELD(0, 1, 0)
+/*
+ * Data Width 4bit SDC_TMR_WTH_4BIT
+ */
+#define SDC_TMR_WTH_4BIT FIELD(1, 1, 0)
+/*
+ * Read SDC_TMR_DIR_READ
+ */
+#define SDC_TMR_DIR_READ FIELD(0, 1, 1)
+/*
+ * Write SDC_TMR_DIR_WRITE
+ */
+#define SDC_TMR_DIR_WRITE FIELD(1, 1, 1)
+
+#define SDC_IR_MASK FMASK(13, 0)
+#define SDC_IR_RESTIMEOUT FIELD(1, 1, 0)
+#define SDC_IR_WRITECRC FIELD(1, 1, 1)
+#define SDC_IR_READCRC FIELD(1, 1, 2)
+#define SDC_IR_TXFIFOREAD FIELD(1, 1, 3)
+#define SDC_IR_RXFIFOWRITE FIELD(1, 1, 4)
+#define SDC_IR_READTIMEOUT FIELD(1, 1, 5)
+#define SDC_IR_DATACOMPLETE FIELD(1, 1, 6)
+#define SDC_IR_CMDCOMPLETE FIELD(1, 1, 7)
+#define SDC_IR_RXFIFOFULL FIELD(1, 1, 8)
+#define SDC_IR_RXFIFOEMPTY FIELD(1, 1, 9)
+#define SDC_IR_TXFIFOFULL FIELD(1, 1, 10)
+#define SDC_IR_TXFIFOEMPTY FIELD(1, 1, 11)
+#define SDC_IR_ENDCMDWITHRES FIELD(1, 1, 12)
diff --git a/arch/unicore32/include/asm/mach/regs-spi.h b/arch/unicore32/include/asm/mach/regs-spi.h
new file mode 100644
index 0000000..cadc713
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-spi.h
@@ -0,0 +1,98 @@
+/*
+ * PKUnity Serial Peripheral Interface (SPI) Registers
+ */
+/*
+ * Control reg. 0 SPI_CR0
+ */
+#define SPI_CR0 __REG(PKUNITY_SPI_BASE + 0x0000)
+/*
+ * Control reg. 1 SPI_CR1
+ */
+#define SPI_CR1 __REG(PKUNITY_SPI_BASE + 0x0004)
+/*
+ * Enable reg SPI_SSIENR
+ */
+#define SPI_SSIENR __REG(PKUNITY_SPI_BASE + 0x0008)
+/*
+ * Status reg SPI_SR
+ */
+#define SPI_SR __REG(PKUNITY_SPI_BASE + 0x0028)
+/*
+ * Interrupt Mask reg SPI_IMR
+ */
+#define SPI_IMR __REG(PKUNITY_SPI_BASE + 0x002C)
+/*
+ * Interrupt Status reg SPI_ISR
+ */
+#define SPI_ISR __REG(PKUNITY_SPI_BASE + 0x0030)
+
+/*
+ * Enable SPI Controller SPI_SSIENR_EN
+ */
+#define SPI_SSIENR_EN FIELD(1, 1, 0)
+
+/*
+ * SPI Busy SPI_SR_BUSY
+ */
+#define SPI_SR_BUSY FIELD(1, 1, 0)
+/*
+ * Transmit FIFO Not Full SPI_SR_TFNF
+ */
+#define SPI_SR_TFNF FIELD(1, 1, 1)
+/*
+ * Transmit FIFO Empty SPI_SR_TFE
+ */
+#define SPI_SR_TFE FIELD(1, 1, 2)
+/*
+ * Receive FIFO Not Empty SPI_SR_RFNE
+ */
+#define SPI_SR_RFNE FIELD(1, 1, 3)
+/*
+ * Receive FIFO Full SPI_SR_RFF
+ */
+#define SPI_SR_RFF FIELD(1, 1, 4)
+
+/*
+ * Trans. FIFO Empty Interrupt Status SPI_ISR_TXEIS
+ */
+#define SPI_ISR_TXEIS FIELD(1, 1, 0)
+/*
+ * Trans. FIFO Overflow Interrupt Status SPI_ISR_TXOIS
+ */
+#define SPI_ISR_TXOIS FIELD(1, 1, 1)
+/*
+ * Receiv. FIFO Underflow Interrupt Status SPI_ISR_RXUIS
+ */
+#define SPI_ISR_RXUIS FIELD(1, 1, 2)
+/*
+ * Receiv. FIFO Overflow Interrupt Status SPI_ISR_RXOIS
+ */
+#define SPI_ISR_RXOIS FIELD(1, 1, 3)
+/*
+ * Receiv. FIFO Full Interrupt Status SPI_ISR_RXFIS
+ */
+#define SPI_ISR_RXFIS FIELD(1, 1, 4)
+#define SPI_ISR_MSTIS FIELD(1, 1, 5)
+
+/*
+ * Trans. FIFO Empty Interrupt Mask SPI_IMR_TXEIM
+ */
+#define SPI_IMR_TXEIM FIELD(1, 1, 0)
+/*
+ * Trans. FIFO Overflow Interrupt Mask SPI_IMR_TXOIM
+ */
+#define SPI_IMR_TXOIM FIELD(1, 1, 1)
+/*
+ * Receiv. FIFO Underflow Interrupt Mask SPI_IMR_RXUIM
+ */
+#define SPI_IMR_RXUIM FIELD(1, 1, 2)
+/*
+ * Receiv. FIFO Overflow Interrupt Mask SPI_IMR_RXOIM
+ */
+#define SPI_IMR_RXOIM FIELD(1, 1, 3)
+/*
+ * Receiv. FIFO Full Interrupt Mask SPI_IMR_RXFIM
+ */
+#define SPI_IMR_RXFIM FIELD(1, 1, 4)
+#define SPI_IMR_MSTIM FIELD(1, 1, 5)
+
diff --git a/arch/unicore32/include/asm/mach/regs-uart.h b/arch/unicore32/include/asm/mach/regs-uart.h
new file mode 100644
index 0000000..9fa6b19
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-uart.h
@@ -0,0 +1,3 @@
+/*
+ * PKUnity Universal Asynchronous Receiver/Transmitter (UART) Registers
+ */
diff --git a/arch/unicore32/include/asm/mach/regs-umal.h b/arch/unicore32/include/asm/mach/regs-umal.h
new file mode 100644
index 0000000..2e718d1
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-umal.h
@@ -0,0 +1,229 @@
+/*
+ * PKUnity Ultra Media Access Layer (UMAL) Ethernet MAC Registers
+ */
+
+/* MAC module of UMAL */
+/* UMAL's MAC module includes G/MII interface, several additional PHY
+ * interfaces, and MAC control sub-layer, which provides support for control
+ * frames (e.g. PAUSE frames).
+ */
+/*
+ * TX/RX reset and control UMAL_CFG1
+ */
+#define UMAL_CFG1 __REG(PKUNITY_UMAL_BASE + 0x0000)
+/*
+ * MAC interface mode control UMAL_CFG2
+ */
+#define UMAL_CFG2 __REG(PKUNITY_UMAL_BASE + 0x0004)
+/*
+ * Inter Packet/Frame Gap UMAL_IPGIFG
+ */
+#define UMAL_IPGIFG __REG(PKUNITY_UMAL_BASE + 0x0008)
+/*
+ * Collision retry or backoff UMAL_HALFDUPLEX
+ */
+#define UMAL_HALFDUPLEX __REG(PKUNITY_UMAL_BASE + 0x000c)
+/*
+ * Maximum Frame Length UMAL_MAXFRAME
+ */
+#define UMAL_MAXFRAME __REG(PKUNITY_UMAL_BASE + 0x0010)
+/*
+ * Test Regsiter UMAL_TESTREG
+ */
+#define UMAL_TESTREG __REG(PKUNITY_UMAL_BASE + 0x001c)
+/*
+ * MII Management Configure UMAL_MIICFG
+ */
+#define UMAL_MIICFG __REG(PKUNITY_UMAL_BASE + 0x0020)
+/*
+ * MII Management Command UMAL_MIICMD
+ */
+#define UMAL_MIICMD __REG(PKUNITY_UMAL_BASE + 0x0024)
+/*
+ * MII Management Address UMAL_MIIADDR
+ */
+#define UMAL_MIIADDR __REG(PKUNITY_UMAL_BASE + 0x0028)
+/*
+ * MII Management Control UMAL_MIICTRL
+ */
+#define UMAL_MIICTRL __REG(PKUNITY_UMAL_BASE + 0x002c)
+/*
+ * MII Management Status UMAL_MIISTATUS
+ */
+#define UMAL_MIISTATUS __REG(PKUNITY_UMAL_BASE + 0x0030)
+/*
+ * MII Managment Indicator UMAL_MIIIDCT
+ */
+#define UMAL_MIIIDCT __REG(PKUNITY_UMAL_BASE + 0x0034)
+/*
+ * Interface Control UMAL_IFCTRL
+ */
+#define UMAL_IFCTRL __REG(PKUNITY_UMAL_BASE + 0x0038)
+/*
+ * Interface Status UMAL_IFSTATUS
+ */
+#define UMAL_IFSTATUS __REG(PKUNITY_UMAL_BASE + 0x003c)
+/*
+ * MAC address (high 4 bytes) UMAL_STADDR1
+ */
+#define UMAL_STADDR1 __REG(PKUNITY_UMAL_BASE + 0x0040)
+/*
+ * MAC address (low 2 bytes) UMAL_STADDR2
+ */
+#define UMAL_STADDR2 __REG(PKUNITY_UMAL_BASE + 0x0044)
+
+/* FIFO MODULE OF UMAL */
+/* UMAL's FIFO module provides data queuing for increased system level
+ * throughput
+ */
+#define UMAL_FIFOCFG0 __REG(PKUNITY_UMAL_BASE + 0x0048)
+#define UMAL_FIFOCFG1 __REG(PKUNITY_UMAL_BASE + 0x004c)
+#define UMAL_FIFOCFG2 __REG(PKUNITY_UMAL_BASE + 0x0050)
+#define UMAL_FIFOCFG3 __REG(PKUNITY_UMAL_BASE + 0x0054)
+#define UMAL_FIFOCFG4 __REG(PKUNITY_UMAL_BASE + 0x0058)
+#define UMAL_FIFOCFG5 __REG(PKUNITY_UMAL_BASE + 0x005c)
+#define UMAL_FIFORAM0 __REG(PKUNITY_UMAL_BASE + 0x0060)
+#define UMAL_FIFORAM1 __REG(PKUNITY_UMAL_BASE + 0x0064)
+#define UMAL_FIFORAM2 __REG(PKUNITY_UMAL_BASE + 0x0068)
+#define UMAL_FIFORAM3 __REG(PKUNITY_UMAL_BASE + 0x006c)
+#define UMAL_FIFORAM4 __REG(PKUNITY_UMAL_BASE + 0x0070)
+#define UMAL_FIFORAM5 __REG(PKUNITY_UMAL_BASE + 0x0074)
+#define UMAL_FIFORAM6 __REG(PKUNITY_UMAL_BASE + 0x0078)
+#define UMAL_FIFORAM7 __REG(PKUNITY_UMAL_BASE + 0x007c)
+
+/* MAHBE MODUEL OF UMAL */
+/* UMAL's MAHBE module interfaces to the host system through 32-bit AHB Master
+ * and Slave ports.Registers within the M-AHBE provide Control and Status
+ * information concerning these transfers.
+ */
+/*
+ * Transmit Control UMAL_DMATxCtrl
+ */
+#define UMAL_DMATxCtrl __REG(PKUNITY_UMAL_BASE + 0x0180)
+/*
+ * Pointer to TX Descripter UMAL_DMATxDescriptor
+ */
+#define UMAL_DMATxDescriptor __REG(PKUNITY_UMAL_BASE + 0x0184)
+/*
+ * Status of Tx Packet Transfers UMAL_DMATxStatus
+ */
+#define UMAL_DMATxStatus __REG(PKUNITY_UMAL_BASE + 0x0188)
+/*
+ * Receive Control UMAL_DMARxCtrl
+ */
+#define UMAL_DMARxCtrl __REG(PKUNITY_UMAL_BASE + 0x018c)
+/*
+ * Pointer to Rx Descriptor UMAL_DMARxDescriptor
+ */
+#define UMAL_DMARxDescriptor __REG(PKUNITY_UMAL_BASE + 0x0190)
+/*
+ * Status of Rx Packet Transfers UMAL_DMARxStatus
+ */
+#define UMAL_DMARxStatus __REG(PKUNITY_UMAL_BASE + 0x0194)
+/*
+ * Interrupt Mask UMAL_DMAIntrMask
+ */
+#define UMAL_DMAIntrMask __REG(PKUNITY_UMAL_BASE + 0x0198)
+/*
+ * Interrupts, read only UMAL_DMAInterrupt
+ */
+#define UMAL_DMAInterrupt __REG(PKUNITY_UMAL_BASE + 0x019c)
+
+/*
+ * Commands for UMAL_CFG1 register
+ */
+#define UMAL_CFG1_TXENABLE FIELD(1, 1, 0)
+#define UMAL_CFG1_RXENABLE FIELD(1, 1, 2)
+#define UMAL_CFG1_TXFLOWCTL FIELD(1, 1, 4)
+#define UMAL_CFG1_RXFLOWCTL FIELD(1, 1, 5)
+#define UMAL_CFG1_CONFLPBK FIELD(1, 1, 8)
+#define UMAL_CFG1_RESET FIELD(1, 1, 31)
+#define UMAL_CFG1_CONFFLCTL (MAC_TX_FLOW_CTL | MAC_RX_FLOW_CTL)
+
+/*
+ * Commands for UMAL_CFG2 register
+ */
+#define UMAL_CFG2_FULLDUPLEX FIELD(1, 1, 0)
+#define UMAL_CFG2_CRCENABLE FIELD(1, 1, 1)
+#define UMAL_CFG2_PADCRC FIELD(1, 1, 2)
+#define UMAL_CFG2_LENGTHCHECK FIELD(1, 1, 4)
+#define UMAL_CFG2_MODEMASK FMASK(2, 8)
+#define UMAL_CFG2_NIBBLEMODE FIELD(1, 2, 8)
+#define UMAL_CFG2_BYTEMODE FIELD(2, 2, 8)
+#define UMAL_CFG2_PREAMBLENMASK FMASK(4, 12)
+#define UMAL_CFG2_DEFPREAMBLEN FIELD(7, 4, 12)
+#define UMAL_CFG2_FD100 (UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_NIBBLEMODE \
+ | UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
+ | UMAL_CFG2_CRCENABLE | UMAL_CFG2_FULLDUPLEX)
+#define UMAL_CFG2_FD1000 (UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_BYTEMODE \
+ | UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
+ | UMAL_CFG2_CRCENABLE | UMAL_CFG2_FULLDUPLEX)
+#define UMAL_CFG2_HD100 (UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_NIBBLEMODE \
+ | UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
+ | UMAL_CFG2_CRCENABLE)
+
+/*
+ * Command for UMAL_IFCTRL register
+ */
+#define UMAL_IFCTRL_RESET FIELD(1, 1, 31)
+
+/*
+ * Command for UMAL_MIICFG register
+ */
+#define UMAL_MIICFG_RESET FIELD(1, 1, 31)
+
+/*
+ * Command for UMAL_MIICMD register
+ */
+#define UMAL_MIICMD_READ FIELD(1, 1, 0)
+
+/*
+ * Command for UMAL_MIIIDCT register
+ */
+#define UMAL_MIIIDCT_BUSY FIELD(1, 1, 0)
+#define UMAL_MIIIDCT_NOTVALID FIELD(1, 1, 2)
+
+/*
+ * Commands for DMATxCtrl regesters
+ */
+#define UMAL_DMA_Enable FIELD(1, 1, 0)
+
+/*
+ * Commands for DMARxCtrl regesters
+ */
+#define UMAL_DMAIntrMask_ENABLEHALFWORD FIELD(1, 1, 16)
+
+/*
+ * Command for DMARxStatus
+ */
+#define CLR_RX_BUS_ERR FIELD(1, 1, 3)
+#define CLR_RX_OVERFLOW FIELD(1, 1, 2)
+#define CLR_RX_PKT FIELD(1, 1, 0)
+
+/*
+ * Command for DMATxStatus
+ */
+#define CLR_TX_BUS_ERR FIELD(1, 1, 3)
+#define CLR_TX_UNDERRUN FIELD(1, 1, 1)
+#define CLR_TX_PKT FIELD(1, 1, 0)
+
+/*
+ * Commands for DMAIntrMask and DMAInterrupt register
+ */
+#define INT_RX_MASK FIELD(0xd, 4, 4)
+#define INT_TX_MASK FIELD(0xb, 4, 0)
+
+#define INT_RX_BUS_ERR FIELD(1, 1, 7)
+#define INT_RX_OVERFLOW FIELD(1, 1, 6)
+#define INT_RX_PKT FIELD(1, 1, 4)
+#define INT_TX_BUS_ERR FIELD(1, 1, 3)
+#define INT_TX_UNDERRUN FIELD(1, 1, 1)
+#define INT_TX_PKT FIELD(1, 1, 0)
+
+/*
+ * MARCOS of UMAL's descriptors
+ */
+#define UMAL_DESC_PACKETSIZE_EMPTY FIELD(1, 1, 31)
+#define UMAL_DESC_PACKETSIZE_NONEMPTY FIELD(0, 1, 31)
+#define UMAL_DESC_PACKETSIZE_SIZEMASK FMASK(12, 0)
+
diff --git a/arch/unicore32/include/asm/mach/regs-unigfx.h b/arch/unicore32/include/asm/mach/regs-unigfx.h
new file mode 100644
index 0000000..58bbd54
--- /dev/null
+++ b/arch/unicore32/include/asm/mach/regs-unigfx.h
@@ -0,0 +1,200 @@
+/*
+ * PKUnity UNIGFX Registers
+ */
+
+#define UDE_BASE (PKUNITY_UNIGFX_BASE + 0x1400)
+#define UGE_BASE (PKUNITY_UNIGFX_BASE + 0x0000)
+
+/*
+ * command reg for UNIGFX DE
+ */
+/*
+ * control reg UDE_CFG
+ */
+#define UDE_CFG __REG(UDE_BASE + 0x0000)
+/*
+ * framebuffer start address reg UDE_FSA
+ */
+#define UDE_FSA __REG(UDE_BASE + 0x0004)
+/*
+ * line size reg UDE_LS
+ */
+#define UDE_LS __REG(UDE_BASE + 0x0008)
+/*
+ * pitch size reg UDE_PS
+ */
+#define UDE_PS __REG(UDE_BASE + 0x000C)
+/*
+ * horizontal active time reg UDE_HAT
+ */
+#define UDE_HAT __REG(UDE_BASE + 0x0010)
+/*
+ * horizontal blank time reg UDE_HBT
+ */
+#define UDE_HBT __REG(UDE_BASE + 0x0014)
+/*
+ * horizontal sync time reg UDE_HST
+ */
+#define UDE_HST __REG(UDE_BASE + 0x0018)
+/*
+ * vertival active time reg UDE_VAT
+ */
+#define UDE_VAT __REG(UDE_BASE + 0x001C)
+/*
+ * vertival blank time reg UDE_VBT
+ */
+#define UDE_VBT __REG(UDE_BASE + 0x0020)
+/*
+ * vertival sync time reg UDE_VST
+ */
+#define UDE_VST __REG(UDE_BASE + 0x0024)
+/*
+ * cursor position UDE_CXY
+ */
+#define UDE_CXY __REG(UDE_BASE + 0x0028)
+/*
+ * cursor front color UDE_CC0
+ */
+#define UDE_CC0 __REG(UDE_BASE + 0x002C)
+/*
+ * cursor background color UDE_CC1
+ */
+#define UDE_CC1 __REG(UDE_BASE + 0x0030)
+/*
+ * video position UDE_VXY
+ */
+#define UDE_VXY __REG(UDE_BASE + 0x0034)
+/*
+ * video start address reg UDE_VSA
+ */
+#define UDE_VSA __REG(UDE_BASE + 0x0040)
+/*
+ * video size reg UDE_VS
+ */
+#define UDE_VS __REG(UDE_BASE + 0x004C)
+
+/*
+ * command reg for UNIGFX GE
+ */
+/*
+ * src xy reg UGE_SRCXY
+ */
+#define UGE_SRCXY __REG(UGE_BASE + 0x0000)
+/*
+ * dst xy reg UGE_DSTXY
+ */
+#define UGE_DSTXY __REG(UGE_BASE + 0x0004)
+/*
+ * pitch reg UGE_PITCH
+ */
+#define UGE_PITCH __REG(UGE_BASE + 0x0008)
+/*
+ * src start reg UGE_SRCSTART
+ */
+#define UGE_SRCSTART __REG(UGE_BASE + 0x000C)
+/*
+ * dst start reg UGE_DSTSTART
+ */
+#define UGE_DSTSTART __REG(UGE_BASE + 0x0010)
+/*
+ * width height reg UGE_WIDHEIGHT
+ */
+#define UGE_WIDHEIGHT __REG(UGE_BASE + 0x0014)
+/*
+ * rop alpah reg UGE_ROPALPHA
+ */
+#define UGE_ROPALPHA __REG(UGE_BASE + 0x0018)
+/*
+ * front color UGE_FCOLOR
+ */
+#define UGE_FCOLOR __REG(UGE_BASE + 0x001C)
+/*
+ * background color UGE_BCOLOR
+ */
+#define UGE_BCOLOR __REG(UGE_BASE + 0x0020)
+/*
+ * src color key for high value UGE_SCH
+ */
+#define UGE_SCH __REG(UGE_BASE + 0x0024)
+/*
+ * dst color key for high value UGE_DCH
+ */
+#define UGE_DCH __REG(UGE_BASE + 0x0028)
+/*
+ * src color key for low value UGE_SCL
+ */
+#define UGE_SCL __REG(UGE_BASE + 0x002C)
+/*
+ * dst color key for low value UGE_DCL
+ */
+#define UGE_DCL __REG(UGE_BASE + 0x0030)
+/*
+ * clip 0 reg UGE_CLIP0
+ */
+#define UGE_CLIP0 __REG(UGE_BASE + 0x0034)
+/*
+ * clip 1 reg UGE_CLIP1
+ */
+#define UGE_CLIP1 __REG(UGE_BASE + 0x0038)
+/*
+ * command reg UGE_COMMAND
+ */
+#define UGE_COMMAND __REG(UGE_BASE + 0x003C)
+/*
+ * pattern 0 UGE_P0
+ */
+#define UGE_P0 __REG(UGE_BASE + 0x0040)
+#define UGE_P1 __REG(UGE_BASE + 0x0044)
+#define UGE_P2 __REG(UGE_BASE + 0x0048)
+#define UGE_P3 __REG(UGE_BASE + 0x004C)
+#define UGE_P4 __REG(UGE_BASE + 0x0050)
+#define UGE_P5 __REG(UGE_BASE + 0x0054)
+#define UGE_P6 __REG(UGE_BASE + 0x0058)
+#define UGE_P7 __REG(UGE_BASE + 0x005C)
+#define UGE_P8 __REG(UGE_BASE + 0x0060)
+#define UGE_P9 __REG(UGE_BASE + 0x0064)
+#define UGE_P10 __REG(UGE_BASE + 0x0068)
+#define UGE_P11 __REG(UGE_BASE + 0x006C)
+#define UGE_P12 __REG(UGE_BASE + 0x0070)
+#define UGE_P13 __REG(UGE_BASE + 0x0074)
+#define UGE_P14 __REG(UGE_BASE + 0x0078)
+#define UGE_P15 __REG(UGE_BASE + 0x007C)
+#define UGE_P16 __REG(UGE_BASE + 0x0080)
+#define UGE_P17 __REG(UGE_BASE + 0x0084)
+#define UGE_P18 __REG(UGE_BASE + 0x0088)
+#define UGE_P19 __REG(UGE_BASE + 0x008C)
+#define UGE_P20 __REG(UGE_BASE + 0x0090)
+#define UGE_P21 __REG(UGE_BASE + 0x0094)
+#define UGE_P22 __REG(UGE_BASE + 0x0098)
+#define UGE_P23 __REG(UGE_BASE + 0x009C)
+#define UGE_P24 __REG(UGE_BASE + 0x00A0)
+#define UGE_P25 __REG(UGE_BASE + 0x00A4)
+#define UGE_P26 __REG(UGE_BASE + 0x00A8)
+#define UGE_P27 __REG(UGE_BASE + 0x00AC)
+#define UGE_P28 __REG(UGE_BASE + 0x00B0)
+#define UGE_P29 __REG(UGE_BASE + 0x00B4)
+#define UGE_P30 __REG(UGE_BASE + 0x00B8)
+#define UGE_P31 __REG(UGE_BASE + 0x00BC)
+
+#define UDE_CFG_DST_MASK FMASK(2, 8)
+#define UDE_CFG_DST8 FIELD(0x0, 2, 8)
+#define UDE_CFG_DST16 FIELD(0x1, 2, 8)
+#define UDE_CFG_DST24 FIELD(0x2, 2, 8)
+#define UDE_CFG_DST32 FIELD(0x3, 2, 8)
+
+/*
+ * GDEN enable UDE_CFG_GDEN_ENABLE
+ */
+#define UDE_CFG_GDEN_ENABLE FIELD(1, 1, 3)
+/*
+ * VDEN enable UDE_CFG_VDEN_ENABLE
+ */
+#define UDE_CFG_VDEN_ENABLE FIELD(1, 1, 4)
+/*
+ * CDEN enable UDE_CFG_CDEN_ENABLE
+ */
+#define UDE_CFG_CDEN_ENABLE FIELD(1, 1, 5)
+/*
+ * TIMEUP enable UDE_CFG_TIMEUP_ENABLE
+ */
+#define UDE_CFG_TIMEUP_ENABLE FIELD(1, 1, 6)
> -----Original Message-----
> From: linux-arch-owner@vger.kernel.org [mailto:linux-arch-owner@vger.kernel.org] On Behalf Of Guan Xuetao
> Sent: Thursday, January 06, 2011 3:57 PM
> To: linux-arch@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [PATCHv1 0/8] unicore32 machine related files: summary
>
> From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
>
> The whole patch could be fetched from:
> git://git.kernel.org/pub/scm/linux/kernel/git/epip/unicore32.git
> with branch name: unicore32.
> And it is divided into three patch sets: core architecture files,
> additional architecture files, and machine related files.
>
> This patch set adds the machine related files for UniCore32 ISA and PKUnity SoC.
>
> Patch 1 adds machine related core files, also including build infrastructure.
>
> Patch 2 add all hardware registers definitions, which are not split and inserted into
> different drivers.
>
> Patch 3 implements arch-specific pci bus driver.
>
> Patch 4 implements arch-specific ps2 dirver.
>
> Patch 5 implements frame buffer driver.
>
> Patch 6 implements ac97 driver.
>
> Patch 7 implements arch-specific i2c bus driver.
>
> Patch 8 implements network driver.
>
> Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
> ---
> arch/unicore32/include/asm/mach/PKUnity.h | 104 ++
> arch/unicore32/include/asm/mach/bitfield.h | 24 +
> arch/unicore32/include/asm/mach/hardware.h | 45 +
> arch/unicore32/include/asm/mach/regs-ac97.h | 32 +
> arch/unicore32/include/asm/mach/regs-dmac.h | 81 +
> arch/unicore32/include/asm/mach/regs-gpio.h | 70 +
> arch/unicore32/include/asm/mach/regs-i2c.h | 63 +
> arch/unicore32/include/asm/mach/regs-intc.h | 28 +
> arch/unicore32/include/asm/mach/regs-nand.h | 79 +
> arch/unicore32/include/asm/mach/regs-ost.h | 92 ++
> arch/unicore32/include/asm/mach/regs-pci.h | 94 ++
> arch/unicore32/include/asm/mach/regs-pm.h | 126 ++
> arch/unicore32/include/asm/mach/regs-ps2.h | 20 +
> arch/unicore32/include/asm/mach/regs-resetc.h | 34 +
> arch/unicore32/include/asm/mach/regs-rtc.h | 37 +
> arch/unicore32/include/asm/mach/regs-sdc.h | 156 ++
> arch/unicore32/include/asm/mach/regs-spi.h | 98 ++
> arch/unicore32/include/asm/mach/regs-uart.h | 3 +
> arch/unicore32/include/asm/mach/regs-umal.h | 229 +++
> arch/unicore32/include/asm/mach/regs-unigfx.h | 200 +++
> arch/unicore32/include/asm/pci.h | 46 +
> arch/unicore32/kernel/pci.c | 404 +++++
> arch/unicore32/kernel/puv3-core.c | 266 ++++
> arch/unicore32/kernel/puv3-nb0916.c | 183 +++
> arch/unicore32/kernel/puv3-smw0919.c | 120 ++
> drivers/input/keyboard/Kconfig | 11 +
> drivers/input/keyboard/atkbd.c | 4 +
> drivers/input/mouse/psmouse-base.c | 41 +
> drivers/input/serio/i8042.h | 2 +
> drivers/pci/Makefile | 1 +
> drivers/staging/puv3/Kconfig | 142 ++
> drivers/staging/puv3/Makefile | 27 +
> drivers/staging/puv3/TODO | 7 +
> drivers/staging/puv3/i8042-ucio.h | 96 ++
> drivers/staging/puv3/nb0916-atkbd.h | 43 +
> drivers/staging/puv3/puv3_ac97.c | 383 +++++
> drivers/staging/puv3/puv3_i2c.c | 325 ++++
> drivers/staging/puv3/puv3_pcm.c | 449 ++++++
> drivers/staging/puv3/puv3_pcm.h | 33 +
> drivers/staging/puv3/puv3_umal.c | 2082 +++++++++++++++++++++++++
> drivers/staging/puv3/puv3_unifb.c | 972 ++++++++++++
> include/linux/fb.h | 2 +
> 42 files changed, 7254 insertions(+), 0 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCHv1 0/8] unicore32 machine related files: summary
2011-01-06 7:56 [PATCHv1 0/8] unicore32 machine related files: summary Guan Xuetao
2011-01-06 8:00 ` Guan Xuetao
2011-01-06 8:02 ` Guan Xuetao
@ 2011-01-06 8:03 ` Guan Xuetao
2011-01-06 8:04 ` Guan Xuetao
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Guan Xuetao @ 2011-01-06 8:03 UTC (permalink / raw)
To: linux-arch, linux-kernel
[PATCHv1 3/8] unicore32 machine related files: pci bus
From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
Patch 3 implements arch-specific pci bus driver.
Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
---
arch/unicore32/include/asm/pci.h | 46 +++++
arch/unicore32/kernel/pci.c | 404 ++++++++++++++++++++++++++++++++++++++
drivers/pci/Makefile | 1 +
3 files changed, 451 insertions(+), 0 deletions(-)
diff --git a/arch/unicore32/include/asm/pci.h b/arch/unicore32/include/asm/pci.h
new file mode 100644
index 0000000..fa54e6f
--- /dev/null
+++ b/arch/unicore32/include/asm/pci.h
@@ -0,0 +1,46 @@
+/*
+ * linux/arch/unicore32/include/asm/pci.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+#ifndef __UNICORE_PCI_H__
+#define __UNICORE_PCI_H__
+
+#ifdef __KERNEL__
+#include <asm-generic/pci-dma-compat.h>
+#include <asm-generic/pci.h>
+#include <asm/mach/hardware.h> /* for PCIBIOS_MIN_* */
+
+static inline void pcibios_set_master(struct pci_dev *dev)
+{
+ /* No special bus mastering setup handling */
+}
+
+static inline void pcibios_penalize_isa_irq(int irq, int active)
+{
+ /* We don't do dynamic PCI IRQ allocation */
+}
+
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+ enum pci_dma_burst_strategy *strat,
+ unsigned long *strategy_parameter)
+{
+ *strat = PCI_DMA_BURST_INFINITY;
+ *strategy_parameter = ~0UL;
+}
+#endif
+
+#define HAVE_PCI_MMAP
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine);
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
new file mode 100644
index 0000000..d4e55e2
--- /dev/null
+++ b/arch/unicore32/kernel/pci.c
@@ -0,0 +1,404 @@
+/*
+ * linux/arch/unicore32/kernel/pci.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ * PCI bios-type initialisation for PCI machines
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+static int debug_pci;
+static int use_firmware;
+
+#define CONFIG_CMD(bus, devfn, where) \
+ (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+static int
+puv3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 *value)
+{
+ PCICFG_ADDR = CONFIG_CMD(bus, devfn, where);
+ switch (size) {
+ case 1:
+ *value = (PCICFG_DATA >> ((where & 3) * 8)) & 0xFF;
+ break;
+ case 2:
+ *value = (PCICFG_DATA >> ((where & 2) * 8)) & 0xFFFF;
+ break;
+ case 4:
+ *value = PCICFG_DATA;
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+puv3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 value)
+{
+ PCICFG_ADDR = CONFIG_CMD(bus, devfn, where);
+ switch (size) {
+ case 1:
+ PCICFG_DATA = (PCICFG_DATA & ~FMASK(8, (where&3)*8))
+ | FIELD(value, 8, (where&3)*8);
+ break;
+ case 2:
+ PCICFG_DATA = (PCICFG_DATA & ~FMASK(16, (where&2)*8))
+ | FIELD(value, 16, (where&2)*8);
+ break;
+ case 4:
+ PCICFG_DATA = value;
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops pci_puv3_ops = {
+ .read = puv3_read_config,
+ .write = puv3_write_config,
+};
+
+void pci_puv3_preinit(void)
+{
+ printk(KERN_DEBUG "PCI: PKUnity PCI Controller Initializing ...\n");
+ /* config PCI bridge base */
+ PCICFG_BRIBASE = PKUNITY_PCIBRI_BASE;
+
+ PCIBRI_AHBCTL0 = 0;
+ PCIBRI_AHBBAR0 = PKUNITY_PCIBRI_BASE | PCIBRI_BARx_MEM;
+ PCIBRI_AHBAMR0 = 0xFFFF0000;
+ PCIBRI_AHBTAR0 = 0;
+
+ PCIBRI_AHBCTL1 = PCIBRI_CTLx_AT;
+ PCIBRI_AHBBAR1 = PKUNITY_PCILIO_BASE | PCIBRI_BARx_IO;
+ PCIBRI_AHBAMR1 = 0xFFFF0000;
+ PCIBRI_AHBTAR1 = 0x00000000;
+
+ PCIBRI_AHBCTL2 = PCIBRI_CTLx_PREF;
+ PCIBRI_AHBBAR2 = PKUNITY_PCIMEM_BASE | PCIBRI_BARx_MEM;
+ PCIBRI_AHBAMR2 = 0xF8000000;
+ PCIBRI_AHBTAR2 = 0;
+
+ PCIBRI_BAR1 = PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM;
+
+ PCIBRI_PCICTL0 = PCIBRI_CTLx_AT | PCIBRI_CTLx_PREF;
+ PCIBRI_PCIBAR0 = PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM;
+ PCIBRI_PCIAMR0 = 0xF8000000;
+ PCIBRI_PCITAR0 = PKUNITY_SDRAM_BASE;
+
+ PCIBRI_CMD = PCIBRI_CMD | PCIBRI_CMD_IO | PCIBRI_CMD_MEM;
+}
+
+static int __init pci_puv3_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (dev->bus->number == 0) {
+#ifdef CONFIG_ARCH_FPGA /* 4 pci slots */
+ if (dev->devfn == 0x00)
+ return IRQ_PCIINTA;
+ else if (dev->devfn == 0x08)
+ return IRQ_PCIINTB;
+ else if (dev->devfn == 0x10)
+ return IRQ_PCIINTC;
+ else if (dev->devfn == 0x18)
+ return IRQ_PCIINTD;
+#endif
+#ifdef CONFIG_PUV3_DB0913 /* 3 pci slots */
+ if (dev->devfn == 0x30)
+ return IRQ_PCIINTB;
+ else if (dev->devfn == 0x60)
+ return IRQ_PCIINTC;
+ else if (dev->devfn == 0x58)
+ return IRQ_PCIINTD;
+#endif
+#if defined(CONFIG_PUV3_NB0916) || defined(CONFIG_PUV3_SMW0919)
+ /* only support 2 pci devices */
+ if (dev->devfn == 0x00)
+ return IRQ_PCIINTC; /* sata */
+#endif
+ }
+ return -1;
+}
+
+/*
+ * Only first 128MB of memory can be accessed via PCI.
+ * We use GFP_DMA to allocate safe buffers to do map/unmap.
+ * This is really ugly and we need a better way of specifying
+ * DMA-capable regions of memory.
+ */
+void __init puv3_pci_adjust_zones(unsigned long *zone_size,
+ unsigned long *zhole_size)
+{
+ unsigned int sz = SZ_128M >> PAGE_SHIFT;
+
+ /*
+ * Only adjust if > 128M on current system
+ */
+ if (zone_size[0] <= sz)
+ return;
+
+ zone_size[1] = zone_size[0] - sz;
+ zone_size[0] = sz;
+ zhole_size[1] = zhole_size[0];
+ zhole_size[0] = 0;
+}
+
+void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+ if (debug_pci)
+ printk(KERN_DEBUG "PCI: Assigning IRQ %02d to %s\n",
+ irq, pci_name(dev));
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/*
+ * If the bus contains any of these devices, then we must not turn on
+ * parity checking of any kind.
+ */
+static inline int pdev_bad_for_parity(struct pci_dev *dev)
+{
+ return 0;
+}
+
+/*
+ * pcibios_fixup_bus - Called after each bus is probed,
+ * but before its children are examined.
+ */
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+ u16 features = PCI_COMMAND_SERR
+ | PCI_COMMAND_PARITY
+ | PCI_COMMAND_FAST_BACK;
+
+ bus->resource[0] = &ioport_resource;
+ bus->resource[1] = &iomem_resource;
+
+ /*
+ * Walk the devices on this bus, working out what we can
+ * and can't support.
+ */
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ u16 status;
+
+ pci_read_config_word(dev, PCI_STATUS, &status);
+
+ /*
+ * If any device on this bus does not support fast back
+ * to back transfers, then the bus as a whole is not able
+ * to support them. Having fast back to back transfers
+ * on saves us one PCI cycle per transaction.
+ */
+ if (!(status & PCI_STATUS_FAST_BACK))
+ features &= ~PCI_COMMAND_FAST_BACK;
+
+ if (pdev_bad_for_parity(dev))
+ features &= ~(PCI_COMMAND_SERR
+ | PCI_COMMAND_PARITY);
+
+ switch (dev->class >> 8) {
+ case PCI_CLASS_BRIDGE_PCI:
+ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
+ status |= PCI_BRIDGE_CTL_PARITY
+ | PCI_BRIDGE_CTL_MASTER_ABORT;
+ status &= ~(PCI_BRIDGE_CTL_BUS_RESET
+ | PCI_BRIDGE_CTL_FAST_BACK);
+ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
+ break;
+
+ case PCI_CLASS_BRIDGE_CARDBUS:
+ pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
+ &status);
+ status |= PCI_CB_BRIDGE_CTL_PARITY
+ | PCI_CB_BRIDGE_CTL_MASTER_ABORT;
+ pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
+ status);
+ break;
+ }
+ }
+
+ /*
+ * Now walk the devices again, this time setting them up.
+ */
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ u16 cmd;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd |= features;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+ L1_CACHE_BYTES >> 2);
+ }
+
+ /*
+ * Propagate the flags to the PCI bridge.
+ */
+ if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ if (features & PCI_COMMAND_FAST_BACK)
+ bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
+ if (features & PCI_COMMAND_PARITY)
+ bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
+ }
+
+ /*
+ * Report what we did for this bus
+ */
+ printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
+ bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
+}
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_fixup_bus);
+#endif
+
+static int __init pci_common_init(void)
+{
+ struct pci_bus *puv3_bus;
+
+ pci_puv3_preinit();
+
+ puv3_bus = pci_scan_bus(0, &pci_puv3_ops, NULL);
+
+ if (!puv3_bus)
+ panic("PCI: unable to scan bus!");
+
+ pci_fixup_irqs(pci_common_swizzle, pci_puv3_map_irq);
+
+ if (!use_firmware) {
+ /*
+ * Size the bridge windows.
+ */
+ pci_bus_size_bridges(puv3_bus);
+
+ /*
+ * Assign resources.
+ */
+ pci_bus_assign_resources(puv3_bus);
+ }
+
+ /*
+ * Tell drivers about devices found.
+ */
+ pci_bus_add_devices(puv3_bus);
+
+ return 0;
+}
+subsys_initcall(pci_common_init);
+
+char * __devinit pcibios_setup(char *str)
+{
+ if (!strcmp(str, "debug")) {
+ debug_pci = 1;
+ return NULL;
+ } else if (!strcmp(str, "firmware")) {
+ use_firmware = 1;
+ return NULL;
+ }
+ return str;
+}
+
+/*
+ * From arch/i386/kernel/pci-i386.c:
+ *
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might be mirrored at 0x0100-0x03ff..
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+ resource_size_t size, resource_size_t align)
+{
+ resource_size_t start = res->start;
+
+ if (res->flags & IORESOURCE_IO && start & 0x300)
+ start = (start + 0x3ff) & ~0x3ff;
+
+ start = (start + align - 1) & ~(align - 1);
+
+ return start;
+}
+
+/**
+ * pcibios_enable_device - Enable I/O and memory.
+ * @dev: PCI device to be enabled
+ */
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for (idx = 0; idx < 6; idx++) {
+ /* Only set up the requested stuff */
+ if (!(mask & (1 << idx)))
+ continue;
+
+ r = dev->resource + idx;
+ if (!r->start && r->end) {
+ printk(KERN_ERR "PCI: Device %s not available because"
+ " of resource collisions\n", pci_name(dev));
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+
+ /*
+ * Bridges (eg, cardbus bridges) need to be fully enabled
+ */
+ if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
+ cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+
+ if (cmd != old_cmd) {
+ printk("PCI: enabling device %s (%04x -> %04x)\n",
+ pci_name(dev), old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ unsigned long phys;
+
+ if (mmap_state == pci_mmap_io)
+ return -EINVAL;
+
+ phys = vma->vm_pgoff;
+
+ /*
+ * Mark this as IO
+ */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start, phys,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+
+ return 0;
+}
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 98e6fdf..77cf813 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
obj-$(CONFIG_X86) += setup-bus.o
obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
+obj-$(CONFIG_UNICORE32) += setup-bus.o setup-irq.o
obj-$(CONFIG_PARISC) += setup-bus.o
obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
obj-$(CONFIG_PPC) += setup-bus.o
> -----Original Message-----
> From: linux-arch-owner@vger.kernel.org [mailto:linux-arch-owner@vger.kernel.org] On Behalf Of Guan Xuetao
> Sent: Thursday, January 06, 2011 3:57 PM
> To: linux-arch@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [PATCHv1 0/8] unicore32 machine related files: summary
>
> From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
>
> The whole patch could be fetched from:
> git://git.kernel.org/pub/scm/linux/kernel/git/epip/unicore32.git
> with branch name: unicore32.
> And it is divided into three patch sets: core architecture files,
> additional architecture files, and machine related files.
>
> This patch set adds the machine related files for UniCore32 ISA and PKUnity SoC.
>
> Patch 1 adds machine related core files, also including build infrastructure.
>
> Patch 2 add all hardware registers definitions, which are not split and inserted into
> different drivers.
>
> Patch 3 implements arch-specific pci bus driver.
>
> Patch 4 implements arch-specific ps2 dirver.
>
> Patch 5 implements frame buffer driver.
>
> Patch 6 implements ac97 driver.
>
> Patch 7 implements arch-specific i2c bus driver.
>
> Patch 8 implements network driver.
>
> Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
> ---
> arch/unicore32/include/asm/mach/PKUnity.h | 104 ++
> arch/unicore32/include/asm/mach/bitfield.h | 24 +
> arch/unicore32/include/asm/mach/hardware.h | 45 +
> arch/unicore32/include/asm/mach/regs-ac97.h | 32 +
> arch/unicore32/include/asm/mach/regs-dmac.h | 81 +
> arch/unicore32/include/asm/mach/regs-gpio.h | 70 +
> arch/unicore32/include/asm/mach/regs-i2c.h | 63 +
> arch/unicore32/include/asm/mach/regs-intc.h | 28 +
> arch/unicore32/include/asm/mach/regs-nand.h | 79 +
> arch/unicore32/include/asm/mach/regs-ost.h | 92 ++
> arch/unicore32/include/asm/mach/regs-pci.h | 94 ++
> arch/unicore32/include/asm/mach/regs-pm.h | 126 ++
> arch/unicore32/include/asm/mach/regs-ps2.h | 20 +
> arch/unicore32/include/asm/mach/regs-resetc.h | 34 +
> arch/unicore32/include/asm/mach/regs-rtc.h | 37 +
> arch/unicore32/include/asm/mach/regs-sdc.h | 156 ++
> arch/unicore32/include/asm/mach/regs-spi.h | 98 ++
> arch/unicore32/include/asm/mach/regs-uart.h | 3 +
> arch/unicore32/include/asm/mach/regs-umal.h | 229 +++
> arch/unicore32/include/asm/mach/regs-unigfx.h | 200 +++
> arch/unicore32/include/asm/pci.h | 46 +
> arch/unicore32/kernel/pci.c | 404 +++++
> arch/unicore32/kernel/puv3-core.c | 266 ++++
> arch/unicore32/kernel/puv3-nb0916.c | 183 +++
> arch/unicore32/kernel/puv3-smw0919.c | 120 ++
> drivers/input/keyboard/Kconfig | 11 +
> drivers/input/keyboard/atkbd.c | 4 +
> drivers/input/mouse/psmouse-base.c | 41 +
> drivers/input/serio/i8042.h | 2 +
> drivers/pci/Makefile | 1 +
> drivers/staging/puv3/Kconfig | 142 ++
> drivers/staging/puv3/Makefile | 27 +
> drivers/staging/puv3/TODO | 7 +
> drivers/staging/puv3/i8042-ucio.h | 96 ++
> drivers/staging/puv3/nb0916-atkbd.h | 43 +
> drivers/staging/puv3/puv3_ac97.c | 383 +++++
> drivers/staging/puv3/puv3_i2c.c | 325 ++++
> drivers/staging/puv3/puv3_pcm.c | 449 ++++++
> drivers/staging/puv3/puv3_pcm.h | 33 +
> drivers/staging/puv3/puv3_umal.c | 2082 +++++++++++++++++++++++++
> drivers/staging/puv3/puv3_unifb.c | 972 ++++++++++++
> include/linux/fb.h | 2 +
> 42 files changed, 7254 insertions(+), 0 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCHv1 0/8] unicore32 machine related files: summary
2011-01-06 7:56 [PATCHv1 0/8] unicore32 machine related files: summary Guan Xuetao
` (2 preceding siblings ...)
2011-01-06 8:03 ` Guan Xuetao
@ 2011-01-06 8:04 ` Guan Xuetao
2011-01-06 8:04 ` Guan Xuetao
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Guan Xuetao @ 2011-01-06 8:04 UTC (permalink / raw)
To: linux-arch, linux-kernel
[PATCHv1 4/8] unicore32 machine related files: ps2 driver
From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
Patch 4 implements arch-specific ps2 driver.
Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
---
drivers/input/keyboard/Kconfig | 11 ++++
drivers/input/keyboard/atkbd.c | 4 ++
drivers/input/mouse/psmouse-base.c | 41 +++++++++++++++
drivers/input/serio/i8042.h | 2 +
drivers/staging/puv3/i8042-ucio.h | 96 +++++++++++++++++++++++++++++++++++
drivers/staging/puv3/nb0916-atkbd.h | 43 ++++++++++++++++
6 files changed, 197 insertions(+), 0 deletions(-)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 3a87f3b..c03c453 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -134,6 +134,17 @@ config KEYBOARD_QT2160
This driver can also be built as a module. If so, the module
will be called qt2160.
+config KEYBOARD_ATKBD_PKUNITY_KEYCODES
+ bool "Use PKUnity keyboard scancodes"
+ depends on ARCH_PUV3 && KEYBOARD_ATKBD
+ default y
+ help
+ Say Y here if you have a PKUnity machine and want to use an AT or
+ PS/2 keyboard, and your keyboard uses keycodes that are specific to
+ PKUnity keyboards.
+
+ Say N if you use a standard keyboard.
+
config KEYBOARD_BFIN
tristate "Blackfin BF54x keypad support"
depends on (BF54x && !BF544)
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 11478eb..c206cf0 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -82,6 +82,10 @@ static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = {
#include "hpps2atkbd.h" /* include the keyboard scancodes */
+#elif CONFIG_KEYBOARD_ATKBD_PKUNITY_KEYCODES
+
+#include "../../staging/puv3/nb0916-atkbd.h"
+
#else
0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index cd9d0c9..d4497f7 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -61,7 +61,11 @@ static unsigned int psmouse_smartscroll = 1;
module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
+#if defined(CONFIG_UNICORE32) && defined(CONFIG_ARCH_PUV3)
+static unsigned int psmouse_resetafter = 1;
+#else
static unsigned int psmouse_resetafter = 5;
+#endif
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
@@ -132,6 +136,27 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
if (psmouse->pktcnt < psmouse->pktsize)
return PSMOUSE_GOOD_DATA;
+#if defined(CONFIG_UNICORE32) && defined(CONFIG_ARCH_PUV3)
+ if (!(packet[0] & 0x8))
+ return PSMOUSE_BAD_DATA;
+ else {
+ if (packet[1] > 127) {
+ if (!(packet[0] & 0x10))
+ return PSMOUSE_BAD_DATA;
+ } else {
+ if ((packet[0] & 0x10))
+ return PSMOUSE_BAD_DATA;
+ }
+
+ if (packet[2] > 127) {
+ if (!(packet[0] & 0x20))
+ return PSMOUSE_BAD_DATA;
+ } else {
+ if ((packet[0] & 0x20))
+ return PSMOUSE_BAD_DATA;
+ }
+ }
+#endif
/*
* Full packet accumulated, process it
*/
@@ -1004,9 +1029,19 @@ static void psmouse_initialize(struct psmouse *psmouse)
static void psmouse_activate(struct psmouse *psmouse)
{
+#if defined(CONFIG_UNICORE32) && defined(CONFIG_ARCH_PUV3)
+ int i;
+ for (i = 0; i < 1000; i++)
+ if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE))
+ printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
+ else
+ break;
+#else
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE))
printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n",
psmouse->ps2dev.serio->phys);
+#endif
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
}
@@ -1413,6 +1448,12 @@ static int psmouse_reconnect(struct serio *serio)
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+#if defined(CONFIG_UNICORE32) && defined(CONFIG_ARCH_PUV3)
+ if (psmouse->protocol_handler(psmouse) == PSMOUSE_BAD_DATA) {
+ if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS))
+ goto out;
+ } else
+#endif
if (psmouse->reconnect) {
if (psmouse->reconnect(psmouse))
goto out;
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
index cbc1beb..711b41c 100644
--- a/drivers/input/serio/i8042.h
+++ b/drivers/input/serio/i8042.h
@@ -26,6 +26,8 @@
#include "i8042-sparcio.h"
#elif defined(CONFIG_X86) || defined(CONFIG_IA64)
#include "i8042-x86ia64io.h"
+#elif defined(CONFIG_UNICORE32)
+#include "../../staging/puv3/i8042-ucio.h"
#else
#include "i8042-io.h"
#endif
diff --git a/drivers/staging/puv3/i8042-ucio.h b/drivers/staging/puv3/i8042-ucio.h
new file mode 100644
index 0000000..1e6e310
--- /dev/null
+++ b/drivers/staging/puv3/i8042-ucio.h
@@ -0,0 +1,96 @@
+/*
+ * linux/drivers/staging/puv3/i8042-ucio.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ * Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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.
+ *
+ * Based on: drivers/input/serio/i8042-io.h
+ *
+ * Contributors & Additions/Fixes:
+ * 2008: First version by HUANG Tao
+ *
+ * TODO:
+ */
+#ifndef _I8042_UCIO_H
+#define _I8042_UCIO_H
+
+#include <asm/mach/hardware.h>
+#include <linux/clk.h>
+
+/*
+ * Names.
+ */
+
+#define I8042_KBD_PHYS_DESC "isa0060/serio0"
+#define I8042_AUX_PHYS_DESC "isa0060/serio1"
+#define I8042_MUX_PHYS_DESC "isa0060/serio%d"
+
+/*
+ * IRQs.
+ */
+#define I8042_KBD_IRQ IRQ_PS2_KBD
+#define I8042_AUX_IRQ IRQ_PS2_AUX
+
+/*
+ * Register numbers.
+ */
+
+#define I8042_COMMAND_REG ((unsigned long)&PS2_COMMAND)
+#define I8042_STATUS_REG ((unsigned long)&PS2_STATUS)
+#define I8042_DATA_REG ((unsigned long)&PS2_DATA)
+
+void puv3_ps2_init(void)
+{
+ struct clk *bclk32;
+
+ bclk32 = clk_get(NULL, "BUS32_CLK");
+ PS2_CNT = clk_get_rate(bclk32) / 200000; /* should > 5us */
+}
+
+static inline int i8042_read_data(void)
+{
+ return inb(I8042_DATA_REG);
+}
+
+static inline int i8042_read_status(void)
+{
+ return inb(I8042_STATUS_REG);
+}
+
+static inline void i8042_write_data(int val)
+{
+ outb(val, I8042_DATA_REG);
+}
+
+static inline void i8042_write_command(int val)
+{
+ outb(val, I8042_COMMAND_REG);
+}
+
+static inline int i8042_platform_init(void)
+{
+/*
+ * On some platforms touching the i8042 data register region can do really
+ * bad things. Because of this the region is always reserved on such boxes.
+ */
+ puv3_ps2_init();
+
+ if (!request_region(I8042_DATA_REG, 16, "i8042"))
+ return -EBUSY;
+
+ i8042_reset = 1;
+ return 0;
+}
+
+static inline void i8042_platform_exit(void)
+{
+ release_region(I8042_DATA_REG, 16);
+}
+
+#endif /* _I8042_UCIO_H */
diff --git a/drivers/staging/puv3/nb0916-atkbd.h b/drivers/staging/puv3/nb0916-atkbd.h
new file mode 100644
index 0000000..2abd398
--- /dev/null
+++ b/drivers/staging/puv3/nb0916-atkbd.h
@@ -0,0 +1,43 @@
+/*
+ * Special Key for NB0916
+ * KEY_CAMERA: 212
+ * KEY_WLAN: 238
+ * KEY_BRIGHTNESSUP: 225
+ * KEY_BRIGHTNESSDOWN: 224
+ * KEY_SWITCHVIDEOMODE: 227
+ */
+ 0, 67, 65, 63, 61, 59, 60, 88,
+ 0, 68, 66, 64, 62, 15, 41, 117,
+ 0, 56, 42, 93, 29, 16, 2, 0,
+ 0, 0, 44, 31, 30, 17, 3, 0,
+ 0, 46, 45, 32, 18, 5, 4, 95,
+ 0, 57, 47, 33, 20, 19, 6, 183,
+ 0, 49, 48, 35, 34, 21, 7, 184,
+ 0, 0, 50, 36, 22, 8, 9, 185,
+ 0, 51, 37, 23, 24, 11, 10, 0,
+ 0, 52, 53, 38, 39, 25, 12, 0,
+ 0, 89, 40, 0, 26, 13, 0, 0,
+ 58, 54, 28, 27, 0, 43, 0, 85,
+ 0, 86, 91, 90, 92, 0, 14, 94,
+ 0, 79, 124, 75, 71, 121, 0, 0,
+ 82, 83, 80, 76, 77, 72, 1, 69,
+ 87, 78, 81, 74, 55, 73, 70, 99,
+
+ 0, 0, 0, 0, 0, 212, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 217, 100, 255, 0, 97, 165, 0, 0,
+ 156, 0, 238, 0, 0, 0, 0, 125,
+ 173, 114, 0, 113, 0, 0, 0, 126,
+ 128, 0, 0, 140, 0, 0, 0, 127,
+ 159, 0, 115, 0, 164, 225, 0, 116,
+ 158, 0, 172, 166, 224, 0, 0, 142,
+ 157, 0, 0, 0, 0, 0, 0, 0,
+ 155, 0, 98, 0, 0, 163, 0, 0,
+ 226, 0, 0, 0, 0, 0, 0, 0,
+ 0, 255, 96, 0, 0, 0, 143, 0,
+ 0, 0, 0, 227, 0, 0, 0, 0,
+ 0, 107, 0, 105, 102, 0, 0, 112,
+ 110, 111, 108, 112, 106, 103, 0, 119,
+ 0, 118, 109, 0, 99, 104, 119, 0,
+
+ 0, 0, 0, 65, 99,
> -----Original Message-----
> From: linux-arch-owner@vger.kernel.org [mailto:linux-arch-owner@vger.kernel.org] On Behalf Of Guan Xuetao
> Sent: Thursday, January 06, 2011 3:57 PM
> To: linux-arch@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [PATCHv1 0/8] unicore32 machine related files: summary
>
> From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
>
> The whole patch could be fetched from:
> git://git.kernel.org/pub/scm/linux/kernel/git/epip/unicore32.git
> with branch name: unicore32.
> And it is divided into three patch sets: core architecture files,
> additional architecture files, and machine related files.
>
> This patch set adds the machine related files for UniCore32 ISA and PKUnity SoC.
>
> Patch 1 adds machine related core files, also including build infrastructure.
>
> Patch 2 add all hardware registers definitions, which are not split and inserted into
> different drivers.
>
> Patch 3 implements arch-specific pci bus driver.
>
> Patch 4 implements arch-specific ps2 dirver.
>
> Patch 5 implements frame buffer driver.
>
> Patch 6 implements ac97 driver.
>
> Patch 7 implements arch-specific i2c bus driver.
>
> Patch 8 implements network driver.
>
> Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
> ---
> arch/unicore32/include/asm/mach/PKUnity.h | 104 ++
> arch/unicore32/include/asm/mach/bitfield.h | 24 +
> arch/unicore32/include/asm/mach/hardware.h | 45 +
> arch/unicore32/include/asm/mach/regs-ac97.h | 32 +
> arch/unicore32/include/asm/mach/regs-dmac.h | 81 +
> arch/unicore32/include/asm/mach/regs-gpio.h | 70 +
> arch/unicore32/include/asm/mach/regs-i2c.h | 63 +
> arch/unicore32/include/asm/mach/regs-intc.h | 28 +
> arch/unicore32/include/asm/mach/regs-nand.h | 79 +
> arch/unicore32/include/asm/mach/regs-ost.h | 92 ++
> arch/unicore32/include/asm/mach/regs-pci.h | 94 ++
> arch/unicore32/include/asm/mach/regs-pm.h | 126 ++
> arch/unicore32/include/asm/mach/regs-ps2.h | 20 +
> arch/unicore32/include/asm/mach/regs-resetc.h | 34 +
> arch/unicore32/include/asm/mach/regs-rtc.h | 37 +
> arch/unicore32/include/asm/mach/regs-sdc.h | 156 ++
> arch/unicore32/include/asm/mach/regs-spi.h | 98 ++
> arch/unicore32/include/asm/mach/regs-uart.h | 3 +
> arch/unicore32/include/asm/mach/regs-umal.h | 229 +++
> arch/unicore32/include/asm/mach/regs-unigfx.h | 200 +++
> arch/unicore32/include/asm/pci.h | 46 +
> arch/unicore32/kernel/pci.c | 404 +++++
> arch/unicore32/kernel/puv3-core.c | 266 ++++
> arch/unicore32/kernel/puv3-nb0916.c | 183 +++
> arch/unicore32/kernel/puv3-smw0919.c | 120 ++
> drivers/input/keyboard/Kconfig | 11 +
> drivers/input/keyboard/atkbd.c | 4 +
> drivers/input/mouse/psmouse-base.c | 41 +
> drivers/input/serio/i8042.h | 2 +
> drivers/pci/Makefile | 1 +
> drivers/staging/puv3/Kconfig | 142 ++
> drivers/staging/puv3/Makefile | 27 +
> drivers/staging/puv3/TODO | 7 +
> drivers/staging/puv3/i8042-ucio.h | 96 ++
> drivers/staging/puv3/nb0916-atkbd.h | 43 +
> drivers/staging/puv3/puv3_ac97.c | 383 +++++
> drivers/staging/puv3/puv3_i2c.c | 325 ++++
> drivers/staging/puv3/puv3_pcm.c | 449 ++++++
> drivers/staging/puv3/puv3_pcm.h | 33 +
> drivers/staging/puv3/puv3_umal.c | 2082 +++++++++++++++++++++++++
> drivers/staging/puv3/puv3_unifb.c | 972 ++++++++++++
> include/linux/fb.h | 2 +
> 42 files changed, 7254 insertions(+), 0 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCHv1 0/8] unicore32 machine related files: summary
2011-01-06 7:56 [PATCHv1 0/8] unicore32 machine related files: summary Guan Xuetao
` (3 preceding siblings ...)
2011-01-06 8:04 ` Guan Xuetao
@ 2011-01-06 8:04 ` Guan Xuetao
2011-01-06 8:05 ` Guan Xuetao
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Guan Xuetao @ 2011-01-06 8:04 UTC (permalink / raw)
To: linux-arch, linux-kernel
[PATCHv1 5/8] unicore32 machine related files: fb driver
From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
Patch 5 implements frame buffer driver.
Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
---
drivers/staging/puv3/puv3_unifb.c | 972 +++++++++++++++++++++++++++++++++++++
include/linux/fb.h | 2 +
2 files changed, 974 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/puv3/puv3_unifb.c b/drivers/staging/puv3/puv3_unifb.c
new file mode 100644
index 0000000..123cf6d
--- /dev/null
+++ b/drivers/staging/puv3/puv3_unifb.c
@@ -0,0 +1,972 @@
+/*
+ * linux/drivers/staging/puv3/puv3_unifb.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ * Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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.
+ *
+ * Based on: drivers/video/vfb.c
+ *
+ * Contributors & Additions/Fixes:
+ * 2008-12-11: First version by ZHONG Qi
+ *
+ * TODO:
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <asm/mach/hardware.h>
+
+static char *unifb_option = NULL;
+static unsigned long unifb_regs[10];
+
+/*
+ * cause UNIGFX don not have EDID
+ * all the modes are organized as follow
+ */
+static const struct fb_videomode unifb_modes[] = {
+ /* 0 640x480-60 VESA */
+ { "640x480@60", 60, 640, 480, 25175000, 48, 16, 34, 10, 96, 1,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1 640x480-75 VESA */
+ { "640x480@75", 75, 640, 480, 31500000, 120, 16, 18, 1, 64, 1,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 2 800x600-60 VESA */
+ { "800x600@60", 60, 800, 600, 40000000, 88, 40, 26, 1, 128, 1,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 3 800x600-75 VESA */
+ { "800x600@75", 75, 800, 600, 49500000, 160, 16, 23, 1, 80, 1,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 4 1024x768-60 VESA */
+ { "1024x768@60", 60, 1024, 768, 65000000, 160, 24, 34, 3, 136, 1,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 5 1024x768-75 VESA */
+ { "1024x768@75", 75, 1024, 768, 78750000, 176, 16, 30, 1, 96, 1,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 6 1280x960-60 VESA */
+ { "1280x960@60", 60, 1280, 960, 108000000, 312, 96, 38, 1, 112, 1,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 7 1440x900-60 VESA */
+ { "1440x900@60", 60, 1440, 900, 106500000, 232, 80, 30, 3, 152, 1,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 8 FIXME 9 1024x600-60 VESA UNTESTED */
+ { "1024x600@60", 60, 1024, 600, 50650000, 160, 24, 26, 1, 136, 1,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 9 FIXME 10 1024x600-75 VESA UNTESTED */
+ { "1024x600@75", 75, 1024, 600, 61500000, 176, 16, 23, 1, 96, 1,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 10 FIXME 11 1366x768-60 VESA UNTESTED */
+ { "1366x768@60", 60, 1366, 768, 85500000, 256, 58, 18, 1, 112, 3,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
+ /*
+ * RAM we reserve for the frame buffer. This defines the maximum screen
+ * size
+ *
+ * The default can be overridden if the driver is compiled as a module
+ */
+#define VIDEOMEMSIZE (4*1024*1024) /* 4 MB for 1024*768*32b */
+
+static void *videomemory;
+static u_long videomemorysize = VIDEOMEMSIZE;
+module_param(videomemorysize, ulong, 0);
+
+static struct fb_var_screeninfo unifb_default = {
+ .xres = 640,
+ .yres = 480,
+ .xres_virtual = 640,
+ .yres_virtual = 480,
+ .bits_per_pixel = 16,
+ .red = { 11, 5, 0 },
+ .green = { 5, 6, 0 },
+ .blue = { 0, 5, 0 },
+ .activate = FB_ACTIVATE_NOW,
+ .height = -1,
+ .width = -1,
+ .pixclock = 25175000,
+ .left_margin = 48,
+ .right_margin = 16,
+ .upper_margin = 33,
+ .lower_margin = 10,
+ .hsync_len = 96,
+ .vsync_len = 2,
+ .vmode = FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo unifb_fix = {
+ .id = "UNIGFX FB",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 1,
+ .ypanstep = 1,
+ .ywrapstep = 1,
+ .accel = FB_ACCEL_NONE,
+};
+
+static int unifb_enable __initdata = 1; /* enable by default */
+module_param(unifb_enable, bool, 0);
+
+static int unifb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int unifb_set_par(struct fb_info *info);
+static int unifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info);
+static int unifb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int unifb_mmap(struct fb_info *info,
+ struct vm_area_struct *vma);
+
+#ifdef CONFIG_PUV3_UNIGFX_HWACCEL
+static void unifb_sync(void)
+{
+ /* TODO: may, this can be replaced by interrupt */
+ int cnt;
+
+ for (cnt = 0; cnt < 0x10000000; cnt++) {
+ if (UGE_COMMAND & 0x1000000)
+ return;
+ }
+
+ if (cnt > 0x8000000)
+ printk(KERN_WARNING "Warning: UniGFX GE time out ...\n");
+}
+
+static void unifb_prim_fillrect(struct fb_info *info,
+ const struct fb_fillrect *region)
+{
+ int awidth = region->width;
+ int aheight = region->height;
+ int m_iBpp = info->var.bits_per_pixel;
+ int screen_width = info->var.xres;
+ int src_sel = 1; /* from fg_color */
+ int pat_sel = 1;
+ int src_x0 = 0;
+ int dst_x0 = region->dx;
+ int src_y0 = 0;
+ int dst_y0 = region->dy;
+ int rop_alpha_sel = 0;
+ int rop_alpha_code = 0xCC;
+ int x_dir = 1;
+ int y_dir = 1;
+ int alpha_r = 0;
+ int alpha_sel = 0;
+ int dst_pitch = screen_width * (m_iBpp / 8);
+ int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
+ int src_pitch = screen_width * (m_iBpp / 8);
+ int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
+ unsigned int command = 0;
+ int clip_region = 0;
+ int clip_en = 0;
+ int tp_en = 0;
+ int fg_color = 0;
+ int bottom = info->var.yres - 1;
+ int right = info->var.xres - 1;
+ int top = 0;
+
+ bottom = (bottom << 16) | right;
+ command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16)
+ | (x_dir << 20) | (y_dir << 21) | (command << 24)
+ | (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
+ src_pitch = (dst_pitch << 16) | src_pitch;
+ awidth = awidth | (aheight << 16);
+ alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff)
+ | (alpha_sel << 16);
+ src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
+ dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
+ fg_color = region->color;
+
+ unifb_sync();
+
+ UGE_FCOLOR = ((u32 *)(info->pseudo_palette))[fg_color];
+ UGE_BCOLOR = 0;
+ UGE_PITCH = src_pitch;
+ UGE_SRCSTART = src_offset;
+ UGE_DSTSTART = dst_offset;
+ UGE_WIDHEIGHT = awidth;
+ UGE_CLIP0 = top;
+ UGE_CLIP1 = bottom;
+ UGE_ROPALPHA = alpha_r;
+ UGE_SRCXY = src_x0;
+ UGE_DSTXY = dst_x0;
+ UGE_COMMAND = command;
+}
+
+static void unifb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *region)
+{
+ struct fb_fillrect modded;
+ int vxres, vyres;
+
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
+ sys_fillrect(info, region);
+ return;
+ }
+
+ vxres = info->var.xres_virtual;
+ vyres = info->var.yres_virtual;
+
+ memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+ if (!modded.width || !modded.height ||
+ modded.dx >= vxres || modded.dy >= vyres)
+ return;
+
+ if (modded.dx + modded.width > vxres)
+ modded.width = vxres - modded.dx;
+ if (modded.dy + modded.height > vyres)
+ modded.height = vyres - modded.dy;
+
+ unifb_prim_fillrect(info, &modded);
+}
+
+static void unifb_prim_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+{
+ int awidth = area->width;
+ int aheight = area->height;
+ int m_iBpp = info->var.bits_per_pixel;
+ int screen_width = info->var.xres;
+ int src_sel = 2; /* from mem */
+ int pat_sel = 0;
+ int src_x0 = area->sx;
+ int dst_x0 = area->dx;
+ int src_y0 = area->sy;
+ int dst_y0 = area->dy;
+
+ int rop_alpha_sel = 0;
+ int rop_alpha_code = 0xCC;
+ int x_dir = 1;
+ int y_dir = 1;
+
+ int alpha_r = 0;
+ int alpha_sel = 0;
+ int dst_pitch = screen_width * (m_iBpp / 8);
+ int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
+ int src_pitch = screen_width * (m_iBpp / 8);
+ int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
+ unsigned int command = 0;
+ int clip_region = 0;
+ int clip_en = 1;
+ int tp_en = 0;
+ int top = 0;
+ int bottom = info->var.yres;
+ int right = info->var.xres;
+ int fg_color = 0;
+ int bg_color = 0;
+
+ if (src_x0 < 0)
+ src_x0 = 0;
+ if (src_y0 < 0)
+ src_y0 = 0;
+
+ if (src_y0 - dst_y0 > 0) {
+ y_dir = 1;
+ } else {
+ y_dir = 0;
+ src_offset = (src_y0 + aheight) * src_pitch +
+ src_x0 * (m_iBpp / 8);
+ dst_offset = (dst_y0 + aheight) * dst_pitch +
+ dst_x0 * (m_iBpp / 8);
+ src_y0 += aheight;
+ dst_y0 += aheight;
+ }
+
+ command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16) |
+ (x_dir << 20) | (y_dir << 21) | (command << 24) |
+ (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
+ src_pitch = (dst_pitch << 16) | src_pitch;
+ awidth = awidth | (aheight << 16);
+ alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff) |
+ (alpha_sel << 16);
+ src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
+ dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
+ bottom = (bottom << 16) | right;
+
+ unifb_sync();
+
+ UGE_PITCH = src_pitch;
+ UGE_SRCSTART = src_offset;
+ UGE_DSTSTART = dst_offset;
+ UGE_WIDHEIGHT = awidth;
+ UGE_CLIP0 = top;
+ UGE_CLIP1 = bottom;
+ UGE_BCOLOR = bg_color;
+ UGE_FCOLOR = fg_color;
+ UGE_ROPALPHA = alpha_r;
+ UGE_SRCXY = src_x0;
+ UGE_DSTXY = dst_x0;
+ UGE_COMMAND = command;
+}
+
+static void unifb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+ struct fb_copyarea modded;
+ u32 vxres, vyres;
+ modded.sx = area->sx;
+ modded.sy = area->sy;
+ modded.dx = area->dx;
+ modded.dy = area->dy;
+ modded.width = area->width;
+ modded.height = area->height;
+
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
+ sys_copyarea(info, area);
+ return;
+ }
+
+ vxres = info->var.xres_virtual;
+ vyres = info->var.yres_virtual;
+
+ if (!modded.width || !modded.height ||
+ modded.sx >= vxres || modded.sy >= vyres ||
+ modded.dx >= vxres || modded.dy >= vyres)
+ return;
+
+ if (modded.sx + modded.width > vxres)
+ modded.width = vxres - modded.sx;
+ if (modded.dx + modded.width > vxres)
+ modded.width = vxres - modded.dx;
+ if (modded.sy + modded.height > vyres)
+ modded.height = vyres - modded.sy;
+ if (modded.dy + modded.height > vyres)
+ modded.height = vyres - modded.dy;
+
+ unifb_prim_copyarea(info, &modded);
+}
+
+static void unifb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+ sys_imageblit(info, image);
+}
+#endif
+
+static struct fb_ops unifb_ops = {
+ .fb_read = fb_sys_read,
+ .fb_write = fb_sys_write,
+ .fb_check_var = unifb_check_var,
+ .fb_set_par = unifb_set_par,
+ .fb_setcolreg = unifb_setcolreg,
+ .fb_pan_display = unifb_pan_display,
+#ifdef CONFIG_PUV3_UNIGFX_HWACCEL
+ .fb_fillrect = unifb_fillrect,
+ .fb_copyarea = unifb_copyarea,
+ .fb_imageblit = unifb_imageblit,
+#else
+ .fb_fillrect = sys_fillrect,
+ .fb_copyarea = sys_copyarea,
+ .fb_imageblit = sys_imageblit,
+#endif
+ .fb_mmap = unifb_mmap,
+};
+
+ /*
+ * Internal routines
+ */
+
+static u_long get_line_length(int xres_virtual, int bpp)
+{
+ u_long length;
+
+ length = xres_virtual * bpp;
+ length = (length + 31) & ~31;
+ length >>= 3;
+ return length;
+}
+
+ /*
+ * Setting the video mode has been split into two parts.
+ * First part, xxxfb_check_var, must not write anything
+ * to hardware, it should only verify and adjust var.
+ * This means it doesn't alter par but it does use hardware
+ * data from it to check this var.
+ */
+
+static int unifb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ u_long line_length;
+
+ /*
+ * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+ * as FB_VMODE_SMOOTH_XPAN is only used internally
+ */
+
+ if (var->vmode & FB_VMODE_CONUPDATE) {
+ var->vmode |= FB_VMODE_YWRAP;
+ var->xoffset = info->var.xoffset;
+ var->yoffset = info->var.yoffset;
+ }
+
+ /*
+ * Some very basic checks
+ */
+ if (!var->xres)
+ var->xres = 1;
+ if (!var->yres)
+ var->yres = 1;
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+ if (var->bits_per_pixel <= 1)
+ var->bits_per_pixel = 1;
+ else if (var->bits_per_pixel <= 8)
+ var->bits_per_pixel = 8;
+ else if (var->bits_per_pixel <= 16)
+ var->bits_per_pixel = 16;
+ else if (var->bits_per_pixel <= 24)
+ var->bits_per_pixel = 24;
+ else if (var->bits_per_pixel <= 32)
+ var->bits_per_pixel = 32;
+ else
+ return -EINVAL;
+
+ if (var->xres_virtual < var->xoffset + var->xres)
+ var->xres_virtual = var->xoffset + var->xres;
+ if (var->yres_virtual < var->yoffset + var->yres)
+ var->yres_virtual = var->yoffset + var->yres;
+
+ /*
+ * Memory limit
+ */
+ line_length =
+ get_line_length(var->xres_virtual, var->bits_per_pixel);
+ if (line_length * var->yres_virtual > videomemorysize)
+ return -ENOMEM;
+
+ /*
+ * Now that we checked it we alter var. The reason being is that the
+ * video mode passed in might not work but slight changes to it might
+ * make it work. This way we let the user know what is acceptable.
+ */
+ switch (var->bits_per_pixel) {
+ case 1:
+ case 8:
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 0;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case 16: /* RGBA 5551 */
+ if (var->transp.length) {
+ var->red.offset = 0;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 5;
+ var->blue.offset = 10;
+ var->blue.length = 5;
+ var->transp.offset = 15;
+ var->transp.length = 1;
+ } else { /* RGB 565 */
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ }
+ break;
+ case 24: /* RGB 888 */
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 16;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case 32: /* RGBA 8888 */
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ break;
+ }
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+
+ return 0;
+}
+
+/* This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
+ */
+static int unifb_set_par(struct fb_info *info)
+{
+ int hTotal, vTotal, hSyncStart, hSyncEnd, vSyncStart, vSyncEnd;
+ int format;
+
+#ifdef CONFIG_PUV3_PM
+ struct clk *clk_vga;
+ u32 pixclk = 0;
+ int i;
+
+ for (i = 0; i <= 10; i++) {
+ if (info->var.xres == unifb_modes[i].xres
+ && info->var.yres == unifb_modes[i].yres
+ && info->var.upper_margin == unifb_modes[i].upper_margin
+ && info->var.lower_margin == unifb_modes[i].lower_margin
+ && info->var.left_margin == unifb_modes[i].left_margin
+ && info->var.right_margin == unifb_modes[i].right_margin
+ && info->var.hsync_len == unifb_modes[i].hsync_len
+ && info->var.vsync_len == unifb_modes[i].vsync_len) {
+ pixclk = unifb_modes[i].pixclock;
+ break;
+ }
+ }
+
+ /* set clock rate */
+ clk_vga = clk_get(NULL, "VGA_CLK");
+ i = 0;
+ if (pixclk != 0) {
+ if (clk_set_rate(clk_vga, pixclk) == 0)
+ i = 1;
+ }
+
+ if (i == 0) { /* set clock failed */
+ info->fix = unifb_fix;
+ info->var = unifb_default;
+ clk_set_rate(clk_vga, unifb_default.pixclock);
+ }
+#endif
+/* config DE */
+ info->fix.line_length = get_line_length(info->var.xres_virtual,
+ info->var.bits_per_pixel);
+
+ hSyncStart = info->var.xres + info->var.right_margin;
+ hSyncEnd = hSyncStart + info->var.hsync_len;
+ hTotal = hSyncEnd + info->var.left_margin;
+
+ vSyncStart = info->var.yres + info->var.lower_margin;
+ vSyncEnd = vSyncStart + info->var.vsync_len;
+ vTotal = vSyncEnd + info->var.upper_margin;
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ format = UDE_CFG_DST8;
+ break;
+ case 16:
+ format = UDE_CFG_DST16;
+ break;
+ case 24:
+ format = UDE_CFG_DST24;
+ break;
+ case 32:
+ format = UDE_CFG_DST32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ UDE_FSA = unifb_regs[0] = PKUNITY_UNIGFX_MMAP_BASE;
+ UDE_LS = unifb_regs[1] = info->var.yres;
+ UDE_PS = unifb_regs[2] = get_line_length(info->var.xres,
+ info->var.bits_per_pixel) >> 3;
+ /* >> 3 for hw. */
+ UDE_HAT = unifb_regs[3] = (hTotal << 16) | (info->var.xres);
+ UDE_HBT = unifb_regs[4] = ((hTotal - 1) << 16) | (info->var.xres - 1);
+ UDE_HST = unifb_regs[5] = ((hSyncEnd - 1) << 16) | (hSyncStart - 1);
+ UDE_VAT = unifb_regs[6] = (vTotal << 16) | (info->var.yres);
+ UDE_VBT = unifb_regs[7] = ((vTotal - 1) << 16) | (info->var.yres - 1);
+ UDE_VST = unifb_regs[8] = ((vSyncEnd - 1) << 16) | (vSyncStart - 1);
+ UDE_CFG = unifb_regs[9] = UDE_CFG_GDEN_ENABLE | UDE_CFG_TIMEUP_ENABLE
+ | format | 0xC0000001;
+
+ return 0;
+}
+
+ /*
+ * Set a single color register. The values supplied are already
+ * rounded down to the hardware's capabilities (according to the
+ * entries in the var structure). Return != 0 for invalid regno.
+ */
+
+static int unifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ if (regno >= 256) /* no. of hw registers */
+ return 1;
+ /*
+ * Program hardware... do anything you want with transp
+ */
+
+ /* grayscale works only partially under directcolor */
+ if (info->var.grayscale) {
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue =
+ (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
+ /* Directcolor:
+ * var->{color}.offset contains start of bitfield
+ * var->{color}.length contains length of bitfield
+ * {hardwarespecific} contains width of RAMDAC
+ * cmap[X] is programmed to (X << red.offset) | (X << green.offset)
+ * | (X << blue.offset)
+ * RAMDAC[X] is programmed to (red, green, blue)
+ *
+ * Pseudocolor:
+ * uses offset = 0 && length = RAMDAC register width.
+ * var->{color}.offset is 0
+ * var->{color}.length contains widht of DAC
+ * cmap is not used
+ * RAMDAC[X] is programmed to (red, green, blue)
+ * Truecolor:
+ * does not use DAC. Usually 3 are present.
+ * var->{color}.offset contains start of bitfield
+ * var->{color}.length contains length of bitfield
+ * cmap is programmed to (red << red.offset) |
+ * (green << green.offset) |
+ * (blue << blue.offset) |
+ * (transp << transp.offset)
+ * RAMDAC does not exist
+ */
+#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ case FB_VISUAL_PSEUDOCOLOR:
+ red = CNVT_TOHW(red, info->var.red.length);
+ green = CNVT_TOHW(green, info->var.green.length);
+ blue = CNVT_TOHW(blue, info->var.blue.length);
+ transp = CNVT_TOHW(transp, info->var.transp.length);
+ break;
+ case FB_VISUAL_DIRECTCOLOR:
+ red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */
+ green = CNVT_TOHW(green, 8);
+ blue = CNVT_TOHW(blue, 8);
+ /* hey, there is bug in transp handling... */
+ transp = CNVT_TOHW(transp, 8);
+ break;
+ }
+#undef CNVT_TOHW
+ /* Truecolor has hardware independent palette */
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+ u32 v;
+
+ if (regno >= 16)
+ return 1;
+
+ v = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ break;
+ case 16:
+ ((u32 *) (info->pseudo_palette))[regno] = v;
+ break;
+ case 24:
+ case 32:
+ ((u32 *) (info->pseudo_palette))[regno] = v;
+ break;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+ /*
+ * Pan or Wrap the Display
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+static int unifb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ if (var->vmode & FB_VMODE_YWRAP) {
+ if (var->yoffset < 0
+ || var->yoffset >= info->var.yres_virtual
+ || var->xoffset)
+ return -EINVAL;
+ } else {
+ if (var->xoffset + var->xres > info->var.xres_virtual ||
+ var->yoffset + var->yres > info->var.yres_virtual)
+ return -EINVAL;
+ }
+ info->var.xoffset = var->xoffset;
+ info->var.yoffset = var->yoffset;
+ if (var->vmode & FB_VMODE_YWRAP)
+ info->var.vmode |= FB_VMODE_YWRAP;
+ else
+ info->var.vmode &= ~FB_VMODE_YWRAP;
+ return 0;
+}
+
+int unifb_mmap(struct fb_info *info,
+ struct vm_area_struct *vma)
+{
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long pos = info->fix.smem_start + offset;
+
+ if (offset + size > info->fix.smem_len)
+ return -EINVAL;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (io_remap_pfn_range(vma, vma->vm_start, pos >> PAGE_SHIFT, size,
+ vma->vm_page_prot))
+ return -EAGAIN;
+
+ vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
+ return 0;
+
+}
+
+#ifndef MODULE
+/*
+ * The virtual framebuffer driver is only enabled if explicitly
+ * requested by passing 'video=unifb:' (or any actual options).
+ */
+static int __init unifb_setup(char *options)
+{
+ char *this_opt;
+
+ unifb_enable = 0;
+
+ if (!options)
+ return 1;
+
+ unifb_enable = 1;
+
+ if (!*options)
+ return 1;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
+ /* Test disable for backwards compatibility */
+ if (!strcmp(this_opt, "disable"))
+ unifb_enable = 0;
+ }
+ return 1;
+}
+#endif /* MODULE */
+
+ /*
+ * Initialisation
+ */
+
+static int unifb_probe(struct platform_device *dev)
+{
+ struct fb_info *info;
+ int retval = -ENOMEM;
+
+ /*
+ * For real video cards we use ioremap.
+ */
+ videomemory = (void *)KUSER_UNIGFX_BASE;
+
+ /*
+ * VFB could clear memory to prevent kernel info
+ * leakage into userspace and set black screen
+ * VGA-based drivers MUST NOT clear memory if
+ * they want to be able to take over vgacon
+ */
+ /* memset(videomemory, 0, videomemorysize); */
+
+ info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
+ if (!info)
+ goto err;
+
+ info->screen_base = (char __iomem *)videomemory;
+ info->fbops = &unifb_ops;
+
+ retval = fb_find_mode(&info->var, info, unifb_option,
+ unifb_modes, 10, &unifb_modes[0], 16);
+
+ if (!retval || (retval == 4))
+ info->var = unifb_default;
+ unifb_fix.smem_start = PKUNITY_UNIGFX_MMAP_BASE;
+ unifb_fix.smem_len = videomemorysize;
+ unifb_fix.mmio_start = PKUNITY_UNIGFX_BASE;
+ info->fix = unifb_fix;
+ info->pseudo_palette = info->par;
+ info->par = NULL;
+ info->flags = FBINFO_FLAG_DEFAULT;
+#ifdef CONFIG_PUV3_UNIGFX_HWACCEL
+ info->fix.accel = FB_ACCEL_PKUNITY_UNIGFX;
+ info->flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
+#else
+ info->flags |= FBINFO_HWACCEL_DISABLED;
+#endif
+
+ retval = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (retval < 0)
+ goto err1;
+
+ retval = register_framebuffer(info);
+ if (retval < 0)
+ goto err2;
+ platform_set_drvdata(dev, info);
+
+ printk(KERN_INFO
+ "fb%d: Virtual frame buffer device, using %ldK of video memory\n",
+ info->node, videomemorysize >> 10);
+ return 0;
+err2:
+ fb_dealloc_cmap(&info->cmap);
+err1:
+ framebuffer_release(info);
+err:
+ return retval;
+}
+
+static int unifb_remove(struct platform_device *dev)
+{
+ struct fb_info *info = platform_get_drvdata(dev);
+
+ if (info) {
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ framebuffer_release(info);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int unifb_resume(struct platform_device *dev)
+{
+ int rc = 0;
+
+ if (dev->dev.power.power_state.event == PM_EVENT_ON)
+ return 0;
+
+ acquire_console_sem();
+
+ if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+ UDE_FSA = unifb_regs[0];
+ UDE_LS = unifb_regs[1];
+ UDE_PS = unifb_regs[2];
+ UDE_HAT = unifb_regs[3];
+ UDE_HBT = unifb_regs[4];
+ UDE_HST = unifb_regs[5];
+ UDE_VAT = unifb_regs[6];
+ UDE_VBT = unifb_regs[7];
+ UDE_VST = unifb_regs[8];
+ UDE_CFG = unifb_regs[9];
+ }
+ dev->dev.power.power_state = PMSG_ON;
+
+ release_console_sem();
+
+ return rc;
+}
+
+static int unifb_suspend(struct platform_device *dev, pm_message_t mesg)
+{
+ if (mesg.event == dev->dev.power.power_state.event)
+ return 0;
+
+ switch (mesg.event) {
+ case PM_EVENT_FREEZE: /* about to take snapshot */
+ case PM_EVENT_PRETHAW: /* before restoring snapshot */
+ goto done;
+ }
+
+ acquire_console_sem();
+
+ /* do nothing... */
+
+ release_console_sem();
+
+done:
+ dev->dev.power.power_state = mesg;
+
+ return 0;
+}
+#else
+#define unifb_resume NULL
+#define unifb_suspend NULL
+#endif
+
+static struct platform_driver unifb_driver = {
+ .probe = unifb_probe,
+ .remove = unifb_remove,
+ .resume = unifb_resume,
+ .suspend = unifb_suspend,
+ .driver = {
+ .name = "unifb",
+ },
+};
+
+static struct platform_device *unifb_device;
+
+static int __init unifb_init(void)
+{
+ int ret = 0;
+
+#ifndef MODULE
+ if (fb_get_options("unifb", &unifb_option))
+ return -ENODEV;
+ unifb_setup(unifb_option);
+#endif
+
+ if (!unifb_enable)
+ return -ENXIO;
+
+ ret = platform_driver_register(&unifb_driver);
+
+ if (!ret) {
+ unifb_device = platform_device_alloc("unifb", 0);
+
+ if (unifb_device)
+ ret = platform_device_add(unifb_device);
+ else
+ ret = -ENOMEM;
+
+ if (ret) {
+ platform_device_put(unifb_device);
+ platform_driver_unregister(&unifb_driver);
+ }
+ }
+
+ return ret;
+}
+
+module_init(unifb_init);
+
+#ifdef MODULE
+static void __exit unifb_exit(void)
+{
+ platform_device_unregister(unifb_device);
+ platform_driver_unregister(&unifb_driver);
+}
+
+module_exit(unifb_exit);
+
+MODULE_LICENSE("GPL v2");
+#endif /* MODULE */
diff --git a/include/linux/fb.h b/include/linux/fb.h
index d1631d3..f88124a 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -152,6 +152,8 @@
#define FB_ACCEL_PROSAVAGE_DDR 0x8d /* S3 ProSavage DDR */
#define FB_ACCEL_PROSAVAGE_DDRK 0x8e /* S3 ProSavage DDR-K */
+#define FB_ACCEL_PKUNITY_UNIGFX 0xe1 /* PKUnity UniGFX */
+
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
> -----Original Message-----
> From: linux-arch-owner@vger.kernel.org [mailto:linux-arch-owner@vger.kernel.org] On Behalf Of Guan Xuetao
> Sent: Thursday, January 06, 2011 3:57 PM
> To: linux-arch@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [PATCHv1 0/8] unicore32 machine related files: summary
>
> From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
>
> The whole patch could be fetched from:
> git://git.kernel.org/pub/scm/linux/kernel/git/epip/unicore32.git
> with branch name: unicore32.
> And it is divided into three patch sets: core architecture files,
> additional architecture files, and machine related files.
>
> This patch set adds the machine related files for UniCore32 ISA and PKUnity SoC.
>
> Patch 1 adds machine related core files, also including build infrastructure.
>
> Patch 2 add all hardware registers definitions, which are not split and inserted into
> different drivers.
>
> Patch 3 implements arch-specific pci bus driver.
>
> Patch 4 implements arch-specific ps2 dirver.
>
> Patch 5 implements frame buffer driver.
>
> Patch 6 implements ac97 driver.
>
> Patch 7 implements arch-specific i2c bus driver.
>
> Patch 8 implements network driver.
>
> Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
> ---
> arch/unicore32/include/asm/mach/PKUnity.h | 104 ++
> arch/unicore32/include/asm/mach/bitfield.h | 24 +
> arch/unicore32/include/asm/mach/hardware.h | 45 +
> arch/unicore32/include/asm/mach/regs-ac97.h | 32 +
> arch/unicore32/include/asm/mach/regs-dmac.h | 81 +
> arch/unicore32/include/asm/mach/regs-gpio.h | 70 +
> arch/unicore32/include/asm/mach/regs-i2c.h | 63 +
> arch/unicore32/include/asm/mach/regs-intc.h | 28 +
> arch/unicore32/include/asm/mach/regs-nand.h | 79 +
> arch/unicore32/include/asm/mach/regs-ost.h | 92 ++
> arch/unicore32/include/asm/mach/regs-pci.h | 94 ++
> arch/unicore32/include/asm/mach/regs-pm.h | 126 ++
> arch/unicore32/include/asm/mach/regs-ps2.h | 20 +
> arch/unicore32/include/asm/mach/regs-resetc.h | 34 +
> arch/unicore32/include/asm/mach/regs-rtc.h | 37 +
> arch/unicore32/include/asm/mach/regs-sdc.h | 156 ++
> arch/unicore32/include/asm/mach/regs-spi.h | 98 ++
> arch/unicore32/include/asm/mach/regs-uart.h | 3 +
> arch/unicore32/include/asm/mach/regs-umal.h | 229 +++
> arch/unicore32/include/asm/mach/regs-unigfx.h | 200 +++
> arch/unicore32/include/asm/pci.h | 46 +
> arch/unicore32/kernel/pci.c | 404 +++++
> arch/unicore32/kernel/puv3-core.c | 266 ++++
> arch/unicore32/kernel/puv3-nb0916.c | 183 +++
> arch/unicore32/kernel/puv3-smw0919.c | 120 ++
> drivers/input/keyboard/Kconfig | 11 +
> drivers/input/keyboard/atkbd.c | 4 +
> drivers/input/mouse/psmouse-base.c | 41 +
> drivers/input/serio/i8042.h | 2 +
> drivers/pci/Makefile | 1 +
> drivers/staging/puv3/Kconfig | 142 ++
> drivers/staging/puv3/Makefile | 27 +
> drivers/staging/puv3/TODO | 7 +
> drivers/staging/puv3/i8042-ucio.h | 96 ++
> drivers/staging/puv3/nb0916-atkbd.h | 43 +
> drivers/staging/puv3/puv3_ac97.c | 383 +++++
> drivers/staging/puv3/puv3_i2c.c | 325 ++++
> drivers/staging/puv3/puv3_pcm.c | 449 ++++++
> drivers/staging/puv3/puv3_pcm.h | 33 +
> drivers/staging/puv3/puv3_umal.c | 2082 +++++++++++++++++++++++++
> drivers/staging/puv3/puv3_unifb.c | 972 ++++++++++++
> include/linux/fb.h | 2 +
> 42 files changed, 7254 insertions(+), 0 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCHv1 0/8] unicore32 machine related files: summary
2011-01-06 7:56 [PATCHv1 0/8] unicore32 machine related files: summary Guan Xuetao
` (4 preceding siblings ...)
2011-01-06 8:04 ` Guan Xuetao
@ 2011-01-06 8:05 ` Guan Xuetao
2011-01-06 8:05 ` Guan Xuetao
2011-01-06 8:06 ` Guan Xuetao
7 siblings, 0 replies; 9+ messages in thread
From: Guan Xuetao @ 2011-01-06 8:05 UTC (permalink / raw)
To: linux-arch, linux-kernel
[PATCHv1 6/8] unicore32 machine related files: ac97
From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
Patch 6 implements ac97 driver.
Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
---
drivers/staging/puv3/puv3_ac97.c | 383 ++++++++++++++++++++++++++++++++
drivers/staging/puv3/puv3_pcm.c | 449 ++++++++++++++++++++++++++++++++++++++
drivers/staging/puv3/puv3_pcm.h | 33 +++
3 files changed, 865 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/puv3/puv3_ac97.c b/drivers/staging/puv3/puv3_ac97.c
new file mode 100644
index 0000000..f02707e
--- /dev/null
+++ b/drivers/staging/puv3/puv3_ac97.c
@@ -0,0 +1,383 @@
+/*
+ * linux/drivers/staging/puv3/puv3_ac97.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ * Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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.
+ *
+ * Based on: sound/arm/pxa2xx-ac97.c
+ *
+ * Contributors & Additions/Fixes:
+ * 2009-07-30: enhance the PM support, resume/suspend can operate
+ * while ac97 is working by ZHONG Qi
+ * 2009-07-23: cause the ac97's flaw, only support fix sample rate
+ * by ZHONG Qi
+ * 2009-07-23: add ac97 PM support by ZHONG Qi
+ * 2009-03-11: First version by ZHONG Qi
+ *
+ * TODO:
+ * 1. local_ac97_read, local_ac97_write and puv3_codec_regs
+ * are involved for fixing bug, about reseting codec automatically
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+
+#include <asm/irq.h>
+#include <linux/mutex.h>
+#include <asm/mach/hardware.h>
+
+#include "puv3_pcm.h"
+
+static DEFINE_MUTEX(car_mutex);
+
+typedef struct {
+ int (*startup)(struct snd_pcm_substream *, void *);
+ void (*shutdown)(struct snd_pcm_substream *, void *);
+ void (*suspend)(void *);
+ void (*resume)(void *);
+ void *priv;
+} puv3_audio_ops_t;
+
+unsigned short puv3_codec_regs[64] = {
+ 0x5990, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8008, 0x8008,
+ 0x8808, 0x8808, 0x8808, 0x8808, 0x8808, 0x0000, 0x8000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x000f, 0x0607, 0x0410, 0xbb80, 0x0000,
+ 0x0000, 0xbb80, 0x0000, 0x0000, 0x0000, 0x2000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2000, 0x2000, 0x000d,
+ 0x044c, 0x044c, 0x0800, 0x0800, 0x0003, 0x0000, 0x0000, 0X4740,
+};
+
+/* TODO This is unnecessary, except for fixing bug */
+unsigned short local_ac97_read(unsigned short reg)
+{
+ return puv3_codec_regs[reg/2];
+}
+
+/* TODO This is unnecessary, except for fixing bug */
+void local_ac97_write(unsigned short reg, unsigned short val)
+{
+ int i = 1000;
+
+ puv3_codec_regs[reg/2] = val;
+
+ PKUNITY_AC97_CRAC = AC97_CODEC_REG(reg) | AC97_CODEC_VAL(val);
+
+ while (!(PKUNITY_AC97_CONR & AC97_CODEC_WRITECOMPLETE)) {
+ if (!(i--)) {
+ printk(KERN_WARNING "AC97: %s timeout\n", __func__);
+ break;
+ }
+ udelay(1);
+ }
+}
+
+static unsigned short puv3_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
+{
+ return puv3_codec_regs[reg/2];
+}
+
+static void puv3_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short val)
+{
+ int i = 1000;
+
+ mutex_lock(&car_mutex);
+
+ if (reg == 0x2 || reg == 0x18)
+ puv3_codec_regs[reg/2] = val & 0x9F1F;
+ else
+ puv3_codec_regs[reg/2] = val;
+
+ PKUNITY_AC97_CRAC = AC97_CODEC_REG(reg) | AC97_CODEC_VAL(val);
+
+ while (!(PKUNITY_AC97_CONR & AC97_CODEC_WRITECOMPLETE)) {
+ if (!(i--)) {
+ printk(KERN_WARNING "AC97: %s timeout\n", __func__);
+ break;
+ }
+ udelay(1);
+ }
+
+ mutex_unlock(&car_mutex);
+}
+
+static void puv3_ac97_reset(struct snd_ac97 *ac97)
+{
+/* int i = 3;
+
+ PKUNITY_AC97_CONR = AC97_CMD_RESET;
+reset:
+ msleep(1);
+
+ if ((PKUNITY_AC97_CONR & 0x2) == 2) {
+ msleep(1);
+ PKUNITY_AC97_CONR = 0x1;
+ if (i--)
+ goto reset;
+ else {
+ ac97_reset_err = -1;
+ printk("AC97 reset error!\n");
+ }
+ }
+*/
+}
+
+static struct snd_ac97_bus_ops puv3_ac97_ops = {
+ .read = puv3_ac97_read,
+ .write = puv3_ac97_write,
+ .reset = puv3_ac97_reset,
+};
+
+static struct puv3_pcm_dma_params puv3_ac97_pcm_out = {
+ .name = "AC97 PCM out",
+ .dev_addr = PKUNITY_AC97_BASE + 0x20, /* OUT FIFO */
+};
+
+static struct puv3_pcm_dma_params puv3_ac97_pcm_in = {
+ .name = "AC97 PCM in",
+ .dev_addr = PKUNITY_AC97_BASE + 0x30, /* IN FIFO */
+};
+
+static struct snd_pcm *puv3_ac97_pcm;
+static struct snd_ac97 *puv3_ac97_ac97;
+
+static int puv3_ac97_pcm_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ puv3_audio_ops_t *platform_ops;
+ int r;
+
+ runtime->hw.channels_min = 2;
+ runtime->hw.channels_max = 2;
+
+ r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ AC97_RATES_FRONT_DAC : AC97_RATES_ADC;
+
+ platform_ops = substream->pcm->card->dev->platform_data;
+ if (platform_ops && platform_ops->startup)
+ return platform_ops->startup(substream, platform_ops->priv);
+ else
+ return 0;
+}
+
+static void puv3_ac97_pcm_shutdown(struct snd_pcm_substream *substream)
+{
+ puv3_audio_ops_t *platform_ops;
+
+ platform_ops = substream->pcm->card->dev->platform_data;
+ if (platform_ops && platform_ops->shutdown)
+ platform_ops->shutdown(substream, platform_ops->priv);
+}
+
+static int puv3_ac97_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
+ return snd_ac97_set_rate(puv3_ac97_ac97, reg, runtime->rate);
+}
+
+static struct puv3_pcm_client puv3_ac97_pcm_client = {
+ .playback_params = &puv3_ac97_pcm_out,
+ .capture_params = &puv3_ac97_pcm_in,
+ .startup = puv3_ac97_pcm_startup,
+ .shutdown = puv3_ac97_pcm_shutdown,
+ .prepare = puv3_ac97_pcm_prepare,
+};
+
+#ifdef CONFIG_PM
+
+static unsigned long ac97_regs[2];
+static unsigned long ac97_dma_regs[4];
+int ac97_dma_ch = 0;
+
+static int puv3_ac97_do_suspend(struct snd_card *card, pm_message_t state)
+{
+ puv3_audio_ops_t *platform_ops = card->dev->platform_data;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
+ snd_pcm_suspend_all(puv3_ac97_pcm);
+ snd_ac97_suspend(puv3_ac97_ac97);
+ if (platform_ops && platform_ops->suspend)
+ platform_ops->suspend(platform_ops->priv);
+
+ /* store DMA & ac97 */
+ ac97_dma_regs[0] = DMAC_SRCADDR(ac97_dma_ch);
+ ac97_dma_regs[1] = DMAC_DESTADDR(ac97_dma_ch);
+ ac97_dma_regs[2] = DMAC_CONTROL(ac97_dma_ch);
+ ac97_dma_regs[3] = DMAC_CONFIG(ac97_dma_ch);
+
+ ac97_regs[0] = PKUNITY_AC97_OUT_FIFO;
+ ac97_regs[1] = PKUNITY_AC97_IN_FIFO;
+
+ return 0;
+}
+
+static int puv3_ac97_do_resume(struct snd_card *card)
+{
+ puv3_audio_ops_t *platform_ops = card->dev->platform_data;
+ int i;
+
+ if (platform_ops && platform_ops->resume)
+ platform_ops->resume(platform_ops->priv);
+ snd_ac97_resume(puv3_ac97_ac97);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+
+ /* restore DMA & codec & AC97 */
+
+ DMAC_SRCADDR(ac97_dma_ch) = ac97_dma_regs[0];
+ DMAC_DESTADDR(ac97_dma_ch) = ac97_dma_regs[1];
+ DMAC_CONTROL(ac97_dma_ch) = ac97_dma_regs[2];
+ DMAC_CONFIG(ac97_dma_ch) = ac97_dma_regs[3];
+
+ for (i = 0; i < 64; i++)
+ local_ac97_write(i*2, puv3_codec_regs[i]);
+
+ PKUNITY_AC97_OCR = AC97_CMD_VPSAMPLE; /* phone @ var sample rate */
+ PKUNITY_AC97_ICR = AC97_CMD_FCSAMPLE; /* mic @ fix sample rate */
+ PKUNITY_AC97_ENABLE = AC97_CMD_ENABLE;
+
+ local_ac97_write(0x2, 0x0000);
+
+ PKUNITY_AC97_OUT_FIFO = ac97_regs[0];
+ PKUNITY_AC97_IN_FIFO = ac97_regs[1];
+
+ return 0;
+}
+
+static int puv3_ac97_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct snd_card *card = platform_get_drvdata(dev);
+ int ret = 0;
+
+ if (card)
+ ret = puv3_ac97_do_suspend(card, PMSG_SUSPEND);
+
+ return ret;
+}
+
+static int puv3_ac97_resume(struct platform_device *dev)
+{
+ struct snd_card *card = platform_get_drvdata(dev);
+ int ret = 0;
+
+ if (card)
+ ret = puv3_ac97_do_resume(card);
+
+ return ret;
+}
+
+#else
+#define puv3_ac97_suspend NULL
+#define puv3_ac97_resume NULL
+#endif
+
+static int __devinit puv3_ac97_probe(struct platform_device *dev)
+{
+ struct snd_card *card;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97_template ac97_template;
+ int ret;
+
+ ret = -ENOMEM;
+ if (snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+ THIS_MODULE, 0, &card) < 0)
+ goto err;
+
+ card->dev = &dev->dev;
+ strncpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
+
+ ret = puv3_pcm_new(card, &puv3_ac97_pcm_client, &puv3_ac97_pcm);
+ if (ret)
+ goto err;
+
+ ret = snd_ac97_bus(card, 0, &puv3_ac97_ops, NULL, &ac97_bus);
+ if (ret)
+ goto err;
+ memset(&ac97_template, 0, sizeof(ac97_template));
+ ret = snd_ac97_mixer(ac97_bus, &ac97_template, &puv3_ac97_ac97);
+ if (ret)
+ goto err;
+
+ snprintf(card->shortname, sizeof(card->shortname),
+ "%s", snd_ac97_get_short_name(puv3_ac97_ac97));
+ snprintf(card->longname, sizeof(card->longname),
+ "%s (%s)", dev->dev.driver->name, card->mixername);
+
+ snd_card_set_dev(card, &dev->dev);
+ ret = snd_card_register(card);
+ if (ret == 0) {
+ platform_set_drvdata(dev, card);
+ /* phone @ var sample rate */
+ PKUNITY_AC97_OCR = AC97_CMD_VPSAMPLE;
+ /* mic @ fix sample rate */
+ PKUNITY_AC97_ICR = AC97_CMD_FCSAMPLE;
+ PKUNITY_AC97_ENABLE = AC97_CMD_ENABLE;
+ return 0;
+ }
+
+err:
+ if (card)
+ snd_card_free(card);
+ return ret;
+}
+
+static int __devexit puv3_ac97_remove(struct platform_device *dev)
+{
+ struct snd_card *card = platform_get_drvdata(dev);
+
+ PKUNITY_AC97_ENABLE = AC97_CMD_DISABLE;
+
+ if (card) {
+ snd_card_free(card);
+ platform_set_drvdata(dev, NULL);
+ }
+
+ return 0;
+}
+
+static struct platform_driver puv3_ac97_driver = {
+ .probe = puv3_ac97_probe,
+ .remove = __devexit_p(puv3_ac97_remove),
+ .suspend = puv3_ac97_suspend,
+ .resume = puv3_ac97_resume,
+ .driver = {
+ .name = "PKUnity-v3-AC97",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init puv3_ac97_init(void)
+{
+ return platform_driver_register(&puv3_ac97_driver);
+}
+
+static void __exit puv3_ac97_exit(void)
+{
+ platform_driver_unregister(&puv3_ac97_driver);
+}
+
+module_init(puv3_ac97_init);
+module_exit(puv3_ac97_exit);
+MODULE_AUTHOR("ZHONG Qi");
+MODULE_DESCRIPTION("AC97 driver for the PKUNITY chip");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/puv3/puv3_pcm.c b/drivers/staging/puv3/puv3_pcm.c
new file mode 100644
index 0000000..53ce7dc
--- /dev/null
+++ b/drivers/staging/puv3/puv3_pcm.c
@@ -0,0 +1,449 @@
+/*
+ * linux/drivers/staging/puv3/puv3_pcm.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ * Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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.
+ *
+ * Based on: sound/arm/pxa2xx-pcm.c
+ *
+ * Contributors & Additions/Fixes:
+ * 2009-07-30: 1. increase the size of dma_buffer for vphone's performance
+ * 2. fix the XRUN bug by setting the dma buffer counter to zero
+ * by ZHONG Qi
+ * 2009-07-23: cause the ac97's flaw, only support fix sample rate
+ * by ZHONG Qi
+ * 2009-03-11: First version by ZHONG Qi
+ *
+ * TODO:
+ * 1. local_ac97_read, local_ac97_write and puv3_codec_regs
+ * are involved for fixing bug, about reseting codec automatically
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/irqreturn.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include <asm/irq.h>
+#include <asm/mach/dma.h>
+#include <asm/mach/hardware.h>
+
+#include "puv3_pcm.h"
+
+#define COUNTER_SIZE 16
+#define PERIOD_SIZE (4 * 1024)
+
+static void kick_dma(int, struct snd_pcm_substream *);
+static unsigned long next_counter(unsigned long);
+
+static const struct snd_pcm_hardware puv3_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .period_bytes_min = PERIOD_SIZE,
+ .period_bytes_max = PERIOD_SIZE,
+ .periods_min = 1,
+ .periods_max = COUNTER_SIZE, /* 2 */
+ .buffer_bytes_max = COUNTER_SIZE * PERIOD_SIZE, /* 8 * 1024 */
+ .fifo_size = 32,
+};
+
+struct puv3_runtime_data {
+ struct puv3_pcm_dma_params *params;
+ unsigned long buffer_counter;
+ size_t period;
+ int dma_lock;
+ int dma_ch;
+ /* TODO add other filed */
+};
+
+static unsigned long next_counter(unsigned long buffer_counter)
+{
+ return ++buffer_counter % COUNTER_SIZE;
+}
+
+static void reload_dma(int dma_ch, struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime,
+ struct puv3_runtime_data *rtd)
+{
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ local_ac97_write(0x2, puv3_codec_regs[0x2/2]);
+ local_ac97_write(0x18, puv3_codec_regs[0x18/2]);
+ local_ac97_write(0x2a, puv3_codec_regs[0x2a/2]);
+ local_ac97_write(0x2c, puv3_codec_regs[0x2c/2]);
+
+ DMAC_SRCADDR(dma_ch) = runtime->dma_addr +
+ rtd->buffer_counter * rtd->period;
+ DMAC_DESTADDR(dma_ch) = rtd->params->dev_addr;
+ DMAC_CONTROL(dma_ch) = DMAC_CONTROL_SIZE_WORD(rtd->period) |
+ DMAC_CONTROL_SI |
+ DMAC_CONTROL_BURST_8BYTE;
+ DMAC_CONFIG(dma_ch) = DMAC_CONFIG_AC97WR;
+ } else {
+ local_ac97_write(0x1C, puv3_codec_regs[0x1C/2]);
+
+ DMAC_DESTADDR(rtd->dma_ch) = runtime->dma_addr +
+ rtd->buffer_counter * rtd->period;
+ DMAC_SRCADDR(rtd->dma_ch) = rtd->params->dev_addr;
+ DMAC_CONTROL(rtd->dma_ch) = DMAC_CONTROL_SIZE_WORD(rtd->period)
+ | DMAC_CONTROL_DI
+ | DMAC_CONTROL_BURST_8BYTE;
+ DMAC_CONFIG(rtd->dma_ch) = DMAC_CONFIG_AC97RD;
+ }
+}
+
+static void kick_dma(int dma_ch, struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime;
+ struct puv3_runtime_data *rtd;
+
+ runtime = substream->runtime;
+ rtd = runtime->private_data;
+
+ rtd->buffer_counter = next_counter(rtd->buffer_counter);
+
+ reload_dma(dma_ch, substream, runtime, rtd);
+
+ puv3_resume_dma(dma_ch);
+
+ return;
+}
+
+static void reset_dma(int dma_ch, struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime;
+ struct puv3_runtime_data *rtd;
+
+ puv3_stop_dma(dma_ch);
+
+ runtime = substream->runtime;
+ rtd = runtime->private_data;
+
+ rtd->buffer_counter = 0;
+
+ reload_dma(dma_ch, substream, runtime, rtd);
+
+ return;
+}
+
+static int puv3_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct puv3_runtime_data *rtd = runtime->private_data;
+ size_t period = params_period_bytes(params);
+ size_t totsize = params_buffer_bytes(params);
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ runtime->dma_bytes = totsize;
+
+ rtd->period = period;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ DMAC_SRCADDR(rtd->dma_ch) = runtime->dma_addr +
+ rtd->buffer_counter * rtd->period;
+ DMAC_DESTADDR(rtd->dma_ch) = rtd->params->dev_addr;
+ DMAC_CONTROL(rtd->dma_ch) = DMAC_CONTROL_SIZE_WORD(rtd->period)
+ | DMAC_CONTROL_SI
+ | DMAC_CONTROL_BURST_8BYTE;
+ DMAC_CONFIG(rtd->dma_ch) = DMAC_CONFIG_AC97WR;
+ } else {
+ DMAC_DESTADDR(rtd->dma_ch) = runtime->dma_addr +
+ rtd->buffer_counter * rtd->period;
+ DMAC_SRCADDR(rtd->dma_ch) = rtd->params->dev_addr;
+ DMAC_CONTROL(rtd->dma_ch) = DMAC_CONTROL_SIZE_WORD(rtd->period)
+ | DMAC_CONTROL_DI
+ | DMAC_CONTROL_BURST_8BYTE;
+ DMAC_CONFIG(rtd->dma_ch) = DMAC_CONFIG_AC97RD;
+ }
+
+ return 0;
+}
+
+static int puv3_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct puv3_runtime_data *rtd = runtime->private_data;
+
+ puv3_stop_dma(rtd->dma_ch);
+ snd_pcm_set_runtime_buffer(substream, NULL);
+
+ return 0;
+}
+
+static int puv3_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct puv3_pcm_client *client = substream->private_data;
+ return client->prepare(substream);
+}
+
+static int puv3_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct puv3_runtime_data *rtd = runtime->private_data;
+ int ret = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ rtd->dma_lock = 0;
+ puv3_resume_dma(rtd->dma_ch);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ rtd->dma_lock = 1;
+ ac97_dma_ch = rtd->dma_ch;
+ reset_dma(rtd->dma_ch, substream);
+ break;
+
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ puv3_resume_dma(rtd->dma_ch);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static void puv3_pcm_dma_irq(int dma_ch, void *dev_id)
+{
+ struct snd_pcm_substream *substream = dev_id;
+ struct puv3_runtime_data *rtd = substream->runtime->private_data;
+
+ if (!rtd->dma_lock)
+ kick_dma(dma_ch, substream);
+
+ snd_pcm_period_elapsed(substream);
+}
+
+static snd_pcm_uframes_t puv3_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct puv3_runtime_data *rtd = substream->runtime->private_data;
+ dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ DMAC_SRCADDR(rtd->dma_ch) : DMAC_DESTADDR(rtd->dma_ch);
+ snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+ if (x == runtime->buffer_size)
+ x = 0;
+ return x;
+}
+
+static int puv3_pcm_hw_rule_mult32(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ struct snd_interval *i = hw_param_interval(params, rule->var);
+ int changed = 0;
+
+ if (i->min & 31) {
+ i->min = (i->min & ~31) + 32;
+ i->openmin = 0;
+ changed = 1;
+ }
+
+ if (i->max & 31) {
+ i->max &= ~31;
+ i->openmax = 0;
+ changed = 1;
+ }
+
+ return changed;
+}
+
+static int puv3_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct puv3_pcm_client *client = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct puv3_runtime_data *rtd;
+ int ret = 0;
+
+ runtime->hw = puv3_pcm_hardware;
+
+ /*
+ * For mysterious reasons (and despite what the manual says)
+ * playback samples are lost if the DMA count is not a multiple
+ * of the DMA burst size. Let's add a rule to enforce that.
+ */
+ ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ puv3_pcm_hw_rule_mult32, NULL,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -1);
+ if (ret)
+ goto out;
+ ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ puv3_pcm_hw_rule_mult32, NULL,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);
+ if (ret)
+ goto out;
+
+ ret = -ENOMEM;
+ rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
+ if (!rtd)
+ goto out;
+
+ rtd->buffer_counter = 0;
+ rtd->dma_lock = 0;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* TODO unnecessary */
+ local_ac97_write(0x2, 0x0000);
+
+ } else {
+ local_ac97_write(0x1A, 0);
+ local_ac97_write(0x1C, 0x0f0f);
+ }
+
+ rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ client->playback_params : client->capture_params;
+ ret = puv3_request_dma(rtd->params->name, DMA_PRIO_HIGH,
+ puv3_pcm_dma_irq, NULL, substream);
+ if (ret < 0)
+ goto err;
+ rtd->dma_ch = ret;
+
+ runtime->private_data = rtd;
+ ret = client->startup(substream);
+ if (!ret)
+ goto out;
+
+ puv3_free_dma(rtd->dma_ch);
+ err:
+ kfree(rtd);
+ out:
+ return ret;
+}
+
+static int puv3_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct puv3_pcm_client *client = substream->private_data;
+ struct puv3_runtime_data *rtd = substream->runtime->private_data;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ local_ac97_write(0x1A, 0);
+ local_ac97_write(0x1C, 0x8000);
+ }
+
+ puv3_free_dma(rtd->dma_ch);
+ client->shutdown(substream);
+ kfree(rtd);
+
+ return 0;
+}
+
+static struct snd_pcm_ops puv3_pcm_ops = {
+ .open = puv3_pcm_open,
+ .close = puv3_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = puv3_pcm_hw_params,
+ .hw_free = puv3_pcm_hw_free,
+ .prepare = puv3_pcm_prepare,
+ .trigger = puv3_pcm_trigger,
+ .pointer = puv3_pcm_pointer,
+};
+
+static int puv3_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = puv3_pcm_hardware.buffer_bytes_max;
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_coherent(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+ dma_cache_sync(pcm->card->dev, &buf->addr, size, DMA_BIDIRECTIONAL);
+ if (!buf->area)
+ return -ENOMEM;
+ buf->bytes = size;
+ return 0;
+}
+
+static void puv3_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+ dma_free_coherent(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+
+static u64 puv3_pcm_dmamask = 0xffffffff;
+
+int puv3_pcm_new(struct snd_card *card, struct puv3_pcm_client *client,
+ struct snd_pcm **rpcm)
+{
+ struct snd_pcm *pcm;
+ int play = client->playback_params ? 1 : 0;
+ int capt = client->capture_params ? 1 : 0;
+ int ret;
+
+ ret = snd_pcm_new(card, "PKUNITY-PCM", 0, play, capt, &pcm);
+ if (ret)
+ goto out;
+
+ pcm->private_data = client;
+ pcm->private_free = puv3_pcm_free_dma_buffers;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &puv3_pcm_dmamask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = 0xffffffff;
+
+ if (play) {
+ int stream = SNDRV_PCM_STREAM_PLAYBACK;
+ snd_pcm_set_ops(pcm, stream, &puv3_pcm_ops);
+ ret = puv3_pcm_preallocate_dma_buffer(pcm, stream);
+ if (ret)
+ goto out;
+ }
+ if (capt) {
+ int stream = SNDRV_PCM_STREAM_CAPTURE;
+ snd_pcm_set_ops(pcm, stream, &puv3_pcm_ops);
+ ret = puv3_pcm_preallocate_dma_buffer(pcm, stream);
+ if (ret)
+ goto out;
+ }
+
+ if (rpcm)
+ *rpcm = pcm;
+ ret = 0;
+
+ out:
+ return ret;
+}
+EXPORT_SYMBOL(puv3_pcm_new);
+
+MODULE_AUTHOR("ZHONG Qi");
+MODULE_DESCRIPTION("PKUNITY PCM DMA module");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/puv3/puv3_pcm.h b/drivers/staging/puv3/puv3_pcm.h
new file mode 100644
index 0000000..aa9be9b
--- /dev/null
+++ b/drivers/staging/puv3/puv3_pcm.h
@@ -0,0 +1,33 @@
+/*
+ * linux/drivers/staging/puv3/puv3_pcm.h
+ *
+ * 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.
+ *
+ * Based on: sound/arm/pxa2xx-pcm.h
+ *
+ * Contributors & Additions/Fixes:
+ * 2009-03-11: First version by ZHONG Qi
+ */
+
+struct puv3_pcm_dma_params {
+ char *name; /* stream identifier */
+ u32 dev_addr; /* device physical address for DMA */
+};
+
+struct puv3_pcm_client {
+ struct puv3_pcm_dma_params *playback_params;
+ struct puv3_pcm_dma_params *capture_params;
+ int (*startup)(struct snd_pcm_substream *);
+ void (*shutdown)(struct snd_pcm_substream *);
+ int (*prepare)(struct snd_pcm_substream *);
+};
+
+extern int puv3_pcm_new(struct snd_card *, struct puv3_pcm_client *,
+ struct snd_pcm **);
+extern void local_ac97_write(unsigned short, unsigned short);
+extern unsigned short local_ac97_read(unsigned short);
+extern unsigned short puv3_codec_regs[];
+extern int ac97_dma_ch;
+
> -----Original Message-----
> From: linux-arch-owner@vger.kernel.org [mailto:linux-arch-owner@vger.kernel.org] On Behalf Of Guan Xuetao
> Sent: Thursday, January 06, 2011 3:57 PM
> To: linux-arch@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [PATCHv1 0/8] unicore32 machine related files: summary
>
> From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
>
> The whole patch could be fetched from:
> git://git.kernel.org/pub/scm/linux/kernel/git/epip/unicore32.git
> with branch name: unicore32.
> And it is divided into three patch sets: core architecture files,
> additional architecture files, and machine related files.
>
> This patch set adds the machine related files for UniCore32 ISA and PKUnity SoC.
>
> Patch 1 adds machine related core files, also including build infrastructure.
>
> Patch 2 add all hardware registers definitions, which are not split and inserted into
> different drivers.
>
> Patch 3 implements arch-specific pci bus driver.
>
> Patch 4 implements arch-specific ps2 dirver.
>
> Patch 5 implements frame buffer driver.
>
> Patch 6 implements ac97 driver.
>
> Patch 7 implements arch-specific i2c bus driver.
>
> Patch 8 implements network driver.
>
> Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
> ---
> arch/unicore32/include/asm/mach/PKUnity.h | 104 ++
> arch/unicore32/include/asm/mach/bitfield.h | 24 +
> arch/unicore32/include/asm/mach/hardware.h | 45 +
> arch/unicore32/include/asm/mach/regs-ac97.h | 32 +
> arch/unicore32/include/asm/mach/regs-dmac.h | 81 +
> arch/unicore32/include/asm/mach/regs-gpio.h | 70 +
> arch/unicore32/include/asm/mach/regs-i2c.h | 63 +
> arch/unicore32/include/asm/mach/regs-intc.h | 28 +
> arch/unicore32/include/asm/mach/regs-nand.h | 79 +
> arch/unicore32/include/asm/mach/regs-ost.h | 92 ++
> arch/unicore32/include/asm/mach/regs-pci.h | 94 ++
> arch/unicore32/include/asm/mach/regs-pm.h | 126 ++
> arch/unicore32/include/asm/mach/regs-ps2.h | 20 +
> arch/unicore32/include/asm/mach/regs-resetc.h | 34 +
> arch/unicore32/include/asm/mach/regs-rtc.h | 37 +
> arch/unicore32/include/asm/mach/regs-sdc.h | 156 ++
> arch/unicore32/include/asm/mach/regs-spi.h | 98 ++
> arch/unicore32/include/asm/mach/regs-uart.h | 3 +
> arch/unicore32/include/asm/mach/regs-umal.h | 229 +++
> arch/unicore32/include/asm/mach/regs-unigfx.h | 200 +++
> arch/unicore32/include/asm/pci.h | 46 +
> arch/unicore32/kernel/pci.c | 404 +++++
> arch/unicore32/kernel/puv3-core.c | 266 ++++
> arch/unicore32/kernel/puv3-nb0916.c | 183 +++
> arch/unicore32/kernel/puv3-smw0919.c | 120 ++
> drivers/input/keyboard/Kconfig | 11 +
> drivers/input/keyboard/atkbd.c | 4 +
> drivers/input/mouse/psmouse-base.c | 41 +
> drivers/input/serio/i8042.h | 2 +
> drivers/pci/Makefile | 1 +
> drivers/staging/puv3/Kconfig | 142 ++
> drivers/staging/puv3/Makefile | 27 +
> drivers/staging/puv3/TODO | 7 +
> drivers/staging/puv3/i8042-ucio.h | 96 ++
> drivers/staging/puv3/nb0916-atkbd.h | 43 +
> drivers/staging/puv3/puv3_ac97.c | 383 +++++
> drivers/staging/puv3/puv3_i2c.c | 325 ++++
> drivers/staging/puv3/puv3_pcm.c | 449 ++++++
> drivers/staging/puv3/puv3_pcm.h | 33 +
> drivers/staging/puv3/puv3_umal.c | 2082 +++++++++++++++++++++++++
> drivers/staging/puv3/puv3_unifb.c | 972 ++++++++++++
> include/linux/fb.h | 2 +
> 42 files changed, 7254 insertions(+), 0 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCHv1 0/8] unicore32 machine related files: summary
2011-01-06 7:56 [PATCHv1 0/8] unicore32 machine related files: summary Guan Xuetao
` (5 preceding siblings ...)
2011-01-06 8:05 ` Guan Xuetao
@ 2011-01-06 8:05 ` Guan Xuetao
2011-01-06 8:06 ` Guan Xuetao
7 siblings, 0 replies; 9+ messages in thread
From: Guan Xuetao @ 2011-01-06 8:05 UTC (permalink / raw)
To: linux-arch, linux-kernel
[PATCHv1 7/8] unicore32 machine related files: i2c bus
From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
Patch 7 implements arch-specific i2c bus driver.
Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
---
drivers/staging/puv3/puv3_i2c.c | 325 +++++++++++++++++++++++++++++++++++++++
1 files changed, 325 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/puv3/puv3_i2c.c b/drivers/staging/puv3/puv3_i2c.c
new file mode 100644
index 0000000..2a118e2
--- /dev/null
+++ b/drivers/staging/puv3/puv3_i2c.c
@@ -0,0 +1,325 @@
+/*
+ * linux/drivers/staging/puv3/puv3_i2c.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ * Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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.
+ *
+ * Based on: drivers/i2c/busses/i2c-at91.c
+ *
+ * Contributors & Additions/Fixes:
+ * 2009-11-05: change loop time for NOT-eeprom
+ * by GUAN Xue-tao & WU Dong-xia
+ * 2009-07-17: add suspend/resume support by WU Dong-xia
+ * 2009-05-30: add support at24c02 by ZHONG Qi
+ * 2009-05-14: add support bq27200 by ZHONG Qi & WU Dong-xia
+ * 2009-05-06: First version by WU Dong-xia
+ *
+ * TODO:
+ * 1. the latnecy from udelay or msleep may be a bit long
+ * change the parameters according to the device
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <asm/mach/hardware.h>
+
+#define DEBUG
+
+static int i2c_reg = -1;
+
+static void __devinit puv3_i2c_hwinit(void)
+{
+ /* Do Noting */
+}
+
+/*
+ * Poll the i2c status register until the specified bit is set.
+ * Returns 0 if timed out (100 msec).
+ */
+static short poll_status(unsigned long bit)
+{
+ int loop_cntr = 1000;
+
+ if (bit & I2C_STATUS_TFNF) {
+ do {
+ udelay(10);
+ } while (!(I2C_STATUS & bit) && (--loop_cntr > 0));
+ } else {
+ /* RXRDY handler */
+ do {
+ if (I2C_TAR == I2C_TAR_EEPROM)
+ msleep(20);
+ else
+ udelay(10);
+ } while (!(I2C_RXFLR & 0xf) && (--loop_cntr > 0));
+ }
+
+ return (loop_cntr > 0);
+}
+
+static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+ /* Read data */
+ while (length--) {
+ if (!poll_status(I2C_STATUS_TFNF)) {
+ dev_dbg(&adap->dev, "Tx FIFO Not Full timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ /* send addr */
+ I2C_DATACMD = i2c_reg | I2C_DATACMD_WRITE;
+
+ /* get ready to next write */
+ i2c_reg++;
+
+ /* send read CMD */
+ I2C_DATACMD = I2C_DATACMD_READ;
+
+ /* wait until the Rx FIFO have available */
+ if (!poll_status(I2C_STATUS_RFNE)) {
+ dev_dbg(&adap->dev, "RXRDY timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ /* read the data to buf */
+ *buf = (I2C_DATACMD & I2C_DATACMD_DAT_MASK);
+ buf++;
+ }
+
+ i2c_reg = -1;
+
+ return 0;
+}
+
+static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+ /* Do nothing but storing the reg_num to a static variable */
+ i2c_reg = *buf;
+ if (i2c_reg == -1) {
+ printk(KERN_WARNING "Error i2c reg\n");
+ return -ETIMEDOUT;
+ }
+
+ if (length == 1)
+ return 0;
+
+ buf++;
+ length--;
+ while (length--) {
+ /* send addr */
+ I2C_DATACMD = i2c_reg | I2C_DATACMD_WRITE;
+
+ /* send write CMD */
+ I2C_DATACMD = *buf | I2C_DATACMD_WRITE;
+
+ /* wait until the Rx FIFO have available */
+ msleep(20);
+
+ /* read the data to buf */
+ i2c_reg++;
+ buf++;
+ }
+
+ i2c_reg = -1;
+
+ return 0;
+}
+
+/*
+ * Generic i2c master transfer entrypoint.
+ *
+ */
+static int puv3_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg,
+ int num)
+{
+ int i, ret;
+ unsigned char swap;
+
+ /* Disable i2c */
+ I2C_ENABLE = I2C_ENABLE_DISABLE;
+
+ /* Set the work mode and speed*/
+ I2C_CON = I2C_CON_MASTER | I2C_CON_SPEED_STD | I2C_CON_SLAVEDISABLE;
+
+ I2C_TAR = pmsg->addr;
+
+ /* Enable i2c */
+ I2C_ENABLE = I2C_ENABLE_ENABLE;
+
+ dev_dbg(&adap->dev, "puv3_i2c_xfer: processing %d messages:\n", num);
+
+ for (i = 0; i < num; i++) {
+ dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
+ pmsg->flags & I2C_M_RD ? "read" : "writ",
+ pmsg->len, pmsg->len > 1 ? "s" : "",
+ pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
+
+ if (pmsg->len && pmsg->buf) { /* sanity check */
+ if (pmsg->flags & I2C_M_RD)
+ ret = xfer_read(adap, pmsg->buf, pmsg->len);
+ else
+ ret = xfer_write(adap, pmsg->buf, pmsg->len);
+
+ if (ret)
+ return ret;
+
+ }
+ dev_dbg(&adap->dev, "transfer complete\n");
+ pmsg++; /* next message */
+ }
+
+ /* XXX: fixup be16_to_cpu in bq27x00_battery.c */
+ if (pmsg->addr == I2C_TAR_PWIC) {
+ swap = pmsg->buf[0];
+ pmsg->buf[0] = pmsg->buf[1];
+ pmsg->buf[1] = swap;
+ }
+
+ return i;
+}
+
+/*
+ * Return list of supported functionality.
+ */
+static u32 puv3_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm puv3_i2c_algorithm = {
+ .master_xfer = puv3_i2c_xfer,
+ .functionality = puv3_i2c_func,
+};
+
+/*
+ * Main initialization routine.
+ */
+static int __devinit puv3_i2c_probe(struct platform_device *pdev)
+{
+ struct i2c_adapter *adapter;
+ struct resource *res;
+ int rc;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ if (!request_mem_region(res->start, resource_size(res), "puv3_i2c"))
+ return -EBUSY;
+
+ adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+ if (adapter == NULL) {
+ dev_err(&pdev->dev, "can't allocate inteface!\n");
+ rc = -ENOMEM;
+ goto fail2;
+ }
+ snprintf(adapter->name, sizeof(adapter->name), "PUV3");
+ adapter->algo = &puv3_i2c_algorithm;
+ adapter->class = I2C_CLASS_HWMON;
+ adapter->dev.parent = &pdev->dev;
+
+ platform_set_drvdata(pdev, adapter);
+
+ puv3_i2c_hwinit(); /* initialize TWI controller */
+
+ rc = i2c_add_numbered_adapter(adapter);
+ if (rc) {
+ dev_err(&pdev->dev, "Adapter %s registration failed\n",
+ adapter->name);
+ goto fail3;
+ }
+
+ dev_info(&pdev->dev, "PKUnity v3 i2c bus driver.\n");
+ return 0;
+
+fail3:
+ platform_set_drvdata(pdev, NULL);
+ kfree(adapter);
+fail2:
+ release_mem_region(res->start, resource_size(res));
+
+ return rc;
+}
+
+static int puv3_i2c_remove(struct platform_device *pdev)
+{
+ struct i2c_adapter *adapter = platform_get_drvdata(pdev);
+ struct resource *res;
+ int rc;
+
+ rc = i2c_del_adapter(adapter);
+ platform_set_drvdata(pdev, NULL);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
+
+ return rc;
+}
+
+#ifdef CONFIG_PM
+static int puv3_i2c_suspend(struct platform_device *dev, pm_message_t state)
+{
+ int poll_count;
+ /* Disable the IIC */
+ I2C_ENABLE = I2C_ENABLE_DISABLE;
+ for (poll_count = 0; poll_count < 50; poll_count++) {
+ if (I2C_ENSTATUS & I2C_ENSTATUS_ENABLE)
+ udelay(25);
+ }
+
+ return 0;
+}
+
+static int puv3_i2c_resume(struct platform_device *dev)
+{
+ return 0 ;
+}
+#else
+#define puv3_i2c_suspend NULL
+#define puv3_i2c_resume NULL
+#endif
+
+MODULE_ALIAS("platform:puv3_i2c");
+
+static struct platform_driver puv3_i2c_driver = {
+ .probe = puv3_i2c_probe,
+ .remove = __devexit_p(puv3_i2c_remove),
+ .suspend = puv3_i2c_suspend,
+ .resume = puv3_i2c_resume,
+ .driver = {
+ .name = "PKUnity-v3-I2C",
+ .owner = THIS_MODULE,
+ }
+};
+
+static int __init puv3_i2c_init(void)
+{
+ return platform_driver_register(&puv3_i2c_driver);
+}
+
+static void __exit puv3_i2c_exit(void)
+{
+ platform_driver_unregister(&puv3_i2c_driver);
+}
+
+module_init(puv3_i2c_init);
+module_exit(puv3_i2c_exit);
+
+MODULE_AUTHOR("WU Dong-xia");
+MODULE_DESCRIPTION("PKUnity v3 I2C driver");
+MODULE_LICENSE("GPL v2");
> -----Original Message-----
> From: linux-arch-owner@vger.kernel.org [mailto:linux-arch-owner@vger.kernel.org] On Behalf Of Guan Xuetao
> Sent: Thursday, January 06, 2011 3:57 PM
> To: linux-arch@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [PATCHv1 0/8] unicore32 machine related files: summary
>
> From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
>
> The whole patch could be fetched from:
> git://git.kernel.org/pub/scm/linux/kernel/git/epip/unicore32.git
> with branch name: unicore32.
> And it is divided into three patch sets: core architecture files,
> additional architecture files, and machine related files.
>
> This patch set adds the machine related files for UniCore32 ISA and PKUnity SoC.
>
> Patch 1 adds machine related core files, also including build infrastructure.
>
> Patch 2 add all hardware registers definitions, which are not split and inserted into
> different drivers.
>
> Patch 3 implements arch-specific pci bus driver.
>
> Patch 4 implements arch-specific ps2 dirver.
>
> Patch 5 implements frame buffer driver.
>
> Patch 6 implements ac97 driver.
>
> Patch 7 implements arch-specific i2c bus driver.
>
> Patch 8 implements network driver.
>
> Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
> ---
> arch/unicore32/include/asm/mach/PKUnity.h | 104 ++
> arch/unicore32/include/asm/mach/bitfield.h | 24 +
> arch/unicore32/include/asm/mach/hardware.h | 45 +
> arch/unicore32/include/asm/mach/regs-ac97.h | 32 +
> arch/unicore32/include/asm/mach/regs-dmac.h | 81 +
> arch/unicore32/include/asm/mach/regs-gpio.h | 70 +
> arch/unicore32/include/asm/mach/regs-i2c.h | 63 +
> arch/unicore32/include/asm/mach/regs-intc.h | 28 +
> arch/unicore32/include/asm/mach/regs-nand.h | 79 +
> arch/unicore32/include/asm/mach/regs-ost.h | 92 ++
> arch/unicore32/include/asm/mach/regs-pci.h | 94 ++
> arch/unicore32/include/asm/mach/regs-pm.h | 126 ++
> arch/unicore32/include/asm/mach/regs-ps2.h | 20 +
> arch/unicore32/include/asm/mach/regs-resetc.h | 34 +
> arch/unicore32/include/asm/mach/regs-rtc.h | 37 +
> arch/unicore32/include/asm/mach/regs-sdc.h | 156 ++
> arch/unicore32/include/asm/mach/regs-spi.h | 98 ++
> arch/unicore32/include/asm/mach/regs-uart.h | 3 +
> arch/unicore32/include/asm/mach/regs-umal.h | 229 +++
> arch/unicore32/include/asm/mach/regs-unigfx.h | 200 +++
> arch/unicore32/include/asm/pci.h | 46 +
> arch/unicore32/kernel/pci.c | 404 +++++
> arch/unicore32/kernel/puv3-core.c | 266 ++++
> arch/unicore32/kernel/puv3-nb0916.c | 183 +++
> arch/unicore32/kernel/puv3-smw0919.c | 120 ++
> drivers/input/keyboard/Kconfig | 11 +
> drivers/input/keyboard/atkbd.c | 4 +
> drivers/input/mouse/psmouse-base.c | 41 +
> drivers/input/serio/i8042.h | 2 +
> drivers/pci/Makefile | 1 +
> drivers/staging/puv3/Kconfig | 142 ++
> drivers/staging/puv3/Makefile | 27 +
> drivers/staging/puv3/TODO | 7 +
> drivers/staging/puv3/i8042-ucio.h | 96 ++
> drivers/staging/puv3/nb0916-atkbd.h | 43 +
> drivers/staging/puv3/puv3_ac97.c | 383 +++++
> drivers/staging/puv3/puv3_i2c.c | 325 ++++
> drivers/staging/puv3/puv3_pcm.c | 449 ++++++
> drivers/staging/puv3/puv3_pcm.h | 33 +
> drivers/staging/puv3/puv3_umal.c | 2082 +++++++++++++++++++++++++
> drivers/staging/puv3/puv3_unifb.c | 972 ++++++++++++
> include/linux/fb.h | 2 +
> 42 files changed, 7254 insertions(+), 0 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCHv1 0/8] unicore32 machine related files: summary
2011-01-06 7:56 [PATCHv1 0/8] unicore32 machine related files: summary Guan Xuetao
` (6 preceding siblings ...)
2011-01-06 8:05 ` Guan Xuetao
@ 2011-01-06 8:06 ` Guan Xuetao
7 siblings, 0 replies; 9+ messages in thread
From: Guan Xuetao @ 2011-01-06 8:06 UTC (permalink / raw)
To: linux-arch, linux-kernel
[PATCHv1 8/8] unicore32 machine related files: network driver
From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
Patch 8 implements network driver.
Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
---
drivers/staging/puv3/puv3_umal.c | 2082 ++++++++++++++++++++++++++++++++++++++
1 files changed, 2082 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/puv3/puv3_umal.c b/drivers/staging/puv3/puv3_umal.c
new file mode 100644
index 0000000..cbd46e2
--- /dev/null
+++ b/drivers/staging/puv3/puv3_umal.c
@@ -0,0 +1,2082 @@
+/*
+ * linux/drivers/staging/puv3/puv3_umal.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ * Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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.
+ *
+ * Based on: drivers/net/sb1250-mac.c
+ *
+ * Contributors & Additions/Fixes:
+ * 2009-05: First version by Tony Hook at PKUNITY Co., Ltd.
+ * 2009-05-06 Tony Hook: modify FIFO regs value
+ * 2009-06-08 Guan Xue-tao: add default mac addr 00:25:9b:ff:00:00
+ * 2009-06-24 ZHAO Ye: add suspend/resume support
+ * 2009-06-25 Tony Hook: correct umal_close handler,
+ * to avoid double-open crash problem
+ * 2009-10-28 Guan Xue-tao: add net_device_ops support
+ *
+ * TODO:
+ */
+
+#include <linux/bug.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/cache.h>
+#include <linux/io.h>
+
+#include <asm/processor.h> /* Processor type for cache alignment. */
+#include <asm/mach/hardware.h>
+
+MODULE_AUTHOR("Tony Hook (PKUNITY Co., Ltd.)");
+MODULE_DESCRIPTION("PKUNITY-3 SOC Ethernet driver");
+MODULE_LICENSE("GPL v2");
+
+/**********************************************************************
+ * Globals
+ ********************************************************************* */
+
+static const char umal_string[] = "PKUnity-v3-UMAL";
+static const char umal_mdio_string[] = "umal-mdio";
+
+struct eth_addr {
+ u8 addr[6];
+};
+
+struct eth_addr hw_addr[1] = {
+ { {0x00, 0x25, 0x9b, 0xff, 0x00, 0x00} }
+};
+
+/**********************************************************************
+ * Simple types
+ ********************************************************************* */
+
+enum umal_speed {
+ umal_speed_none = 0,
+ umal_speed_10 = SPEED_10,
+ umal_speed_100 = SPEED_100,
+ umal_speed_1000 = SPEED_1000,
+};
+
+enum umal_duplex {
+ umal_duplex_none = -1,
+ umal_duplex_half = DUPLEX_HALF,
+ umal_duplex_full = DUPLEX_FULL,
+};
+
+enum umal_fc {
+ umal_fc_none,
+ umal_fc_disabled,
+ umal_fc_frame,
+ umal_fc_collision,
+ umal_fc_carrier,
+};
+
+enum umal_state {
+ umal_state_uninit,
+ umal_state_off,
+ umal_state_on,
+ umal_state_broken,
+};
+
+/**********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define UMALDMA_NEXTBUF(d, f) ((((d)->f+1) == (d)->umaldma_dscrtable_end) ? \
+ (d)->umaldma_dscrtable : (d)->f+1)
+
+#define DMA_RX 0
+#define DMA_TX 1
+
+#define UMAL_MAX_TXDESCR 256
+#define UMAL_MAX_RXDESCR 256
+
+#define ETHER_ADDR_LEN 6
+#define ENET_PACKET_SIZE 1518
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT (2*HZ)
+
+/**********************************************************************
+ * DMA Descriptor structure
+ ********************************************************************* */
+
+struct umaldmadscr {
+ dma_addr_t PacketStartAddr;
+ int PacketSize;
+ dma_addr_t NextDescriptor;
+ struct umaldmadscr *NextDescriptor_Virt;
+};
+
+/**********************************************************************
+ * DMA Controller structure
+ ********************************************************************* */
+
+struct umaldma {
+ /*
+ * This stuff is used to identify the channel and the registers
+ * associated with it.
+ */
+ /* back pointer to associated MAC */
+ struct umal_softc *umaldma_eth;
+ /* direction (1=transmit) */
+ int umaldma_txdir;
+ /* total # of descriptors in ring */
+ int umaldma_maxdescr;
+ /*
+ * This stuff is for maintenance of the ring
+ */
+ /* base of descriptor table */
+ struct umaldmadscr *umaldma_dscrtable;
+ void *umaldma_dscrtable_unaligned;
+ /* and also the phys addr */
+ dma_addr_t umaldma_dscrtable_phys;
+ /* and also the phys addr */
+ dma_addr_t umaldma_dscrtable_phys_unaligned;
+ /* end of descriptor table */
+ struct umaldmadscr *umaldma_dscrtable_end;
+ /* context table, one per descr */
+ struct sk_buff **umaldma_ctxtable;
+ /* next dscr for sw to add */
+ struct umaldmadscr *umaldma_addptr;
+ /* next dscr for sw to remove */
+ struct umaldmadscr *umaldma_remptr;
+};
+
+/**********************************************************************
+ * Ethernet softc structure
+ ********************************************************************* */
+
+struct umal_softc {
+
+ /*
+ * Linux-specific things
+ */
+ struct net_device *umal_dev; /* pointer to linux device */
+ int umal_idx;
+ struct phy_device *phy_dev; /* the associated PHY device */
+ struct mii_bus *mii_bus; /* the MII bus */
+ int phy_irq[PHY_MAX_ADDR];
+ spinlock_t umal_lock; /* spin lock */
+ int umal_devflags; /* current device flags */
+
+ /*
+ * Controller-specific things
+ */
+ enum umal_state umal_state; /* current state */
+ unsigned char umal_hwaddr[ETHER_ADDR_LEN];
+
+ enum umal_speed umal_speed; /* current speed */
+ enum umal_duplex umal_duplex; /* current duplex */
+ enum umal_fc umal_fc; /* cur. flow control setting */
+ int umal_pause; /* current pause setting */
+ int umal_link; /* current link state */
+
+ struct umaldma umal_rxdma; /* rx dma channel */
+ struct umaldma umal_txdma; /* tx dma channel */
+};
+
+/**********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int umal_mii_reset(struct mii_bus *bus);
+static int umal_mii_read(struct mii_bus *bus, int phyaddr, int regidx);
+static int umal_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
+ u16 val);
+static int umal_mii_probe(struct net_device *dev);
+
+static void umaldma_initctx(struct umaldma *d, struct umal_softc *s,
+ int rxtx, int maxdescr);
+static void umaldma_uninitctx(struct umaldma *d);
+static void umaldma_channel_start(struct umaldma *d, int rxtx);
+static void umaldma_channel_stop(struct umaldma *d);
+static int umaldma_add_rcvbuffer(struct umal_softc *sc, struct umaldma *d,
+ struct sk_buff *m);
+static int umaldma_add_txbuffer(struct umaldma *d, struct sk_buff *m);
+static void umaldma_emptyring(struct umaldma *d);
+static void umaldma_fillring(struct umal_softc *sc, struct umaldma *d);
+static int umaldma_rx_process(struct umal_softc *sc, struct umaldma *d,
+ int work_to_do, int poll);
+static void umaldma_tx_process(struct umal_softc *sc, struct umaldma *d,
+ int poll);
+
+static int umal_initctx(struct umal_softc *s);
+static void umal_uninitctx(struct umal_softc *s);
+static void umal_channel_start(struct umal_softc *s);
+static void umal_channel_stop(struct umal_softc *s);
+static enum umal_state umal_set_channel_state(struct umal_softc *,
+ enum umal_state);
+
+static int umal_init(struct platform_device *pldev, long long base);
+static int umal_open(struct net_device *dev);
+static int umal_close(struct net_device *dev);
+static int umal_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static irqreturn_t umal_intr(int irq, void *dev_instance);
+static void umal_clr_intr(struct net_device *dev);
+static int umal_start_tx(struct sk_buff *skb, struct net_device *dev);
+static void umal_tx_timeout(struct net_device *dev);
+static void umal_set_rx_mode(struct net_device *dev);
+static void umal_promiscuous_mode(struct umal_softc *sc, int onoff);
+static void umal_setmulti(struct umal_softc *sc);
+static int umal_set_speed(struct umal_softc *s, enum umal_speed speed);
+static int umal_set_duplex(struct umal_softc *s, enum umal_duplex duplex,
+ enum umal_fc fc);
+static int umal_change_mtu(struct net_device *_dev, int new_mtu);
+static void umal_miipoll(struct net_device *dev);
+
+/**********************************************************************
+ * MII Bus functions for PAL (phy abstraction layer)
+ ********************************************************************* */
+
+/**********************************************************************
+ * UMAL_MII_RESET(bus)
+ *
+ * Reset MII bus.
+ *
+ * Input parameters:
+ * bus - MDIO bus handle
+ *
+ * Return value:
+ * 0 if ok
+ ********************************************************************* */
+static int umal_mii_reset(struct mii_bus *bus)
+{
+ UMAL_MIICFG = UMAL_MIICFG_RESET; /* reset the MII management */
+ UMAL_MIICFG = 0x0; /* enable the MII management */
+ UMAL_MIICFG |= 0x7; /* source clock division = 28 */
+
+ return 0;
+}
+
+/**********************************************************************
+ * UMAL_MII_READ(bus, phyaddr, regidx)
+ * Read a PHY register.
+ *
+ * Input parameters:
+ * bus - MDIO bus handle
+ * phyaddr - PHY's address
+ * regnum - index of register to read
+ *
+ * Return value:
+ * value read, or 0xffff if an error occurred.
+ ********************************************************************* */
+static int umal_mii_read(struct mii_bus *bus, int phyaddr, int regidx)
+{
+ int tmp = 0;
+
+ UMAL_MIIADDR = (phyaddr<<8) | regidx;
+ UMAL_MIICMD = UMAL_MIICMD_READ;
+
+ tmp = UMAL_MIIIDCT;
+ while (tmp & UMAL_MIIIDCT_BUSY)
+ tmp = UMAL_MIIIDCT;
+
+ if (tmp & UMAL_MIIIDCT_NOTVALID)
+ return 0xffff;
+
+ UMAL_MIICMD = 0;
+
+ tmp = UMAL_MIISTATUS;
+ return tmp;
+}
+
+/**********************************************************************
+ * UMAL_MII_WRITE(bus, phyaddr, regidx, regval)
+ *
+ * Write a value to a PHY register.
+ *
+ * Input parameters:
+ * bus - MDIO bus handle
+ * phyaddr - PHY to use
+ * regidx - register within the PHY
+ * regval - data to write to register
+ *
+ * Return value:
+ * 0 if ok
+ ********************************************************************* */
+static int umal_mii_write(struct mii_bus *bus, int phyaddr, int regidx, u16 val)
+{
+ int tmp = 0;
+
+ UMAL_MIIADDR = (phyaddr<<8) | regidx;
+ UMAL_MIICTRL = val;
+
+ tmp = UMAL_MIIIDCT;
+ while (tmp & UMAL_MIIIDCT_BUSY)
+ tmp = UMAL_MIIIDCT;
+
+ return 0;
+}
+
+/**********************************************************************
+ * UMAL_MII_PROBE(dev)
+ *
+ * Write a value to a PHY register.
+ *
+ * Input parameters:
+ * dev - net_device structure
+ *
+ * Return value:
+ * 0 if ok
+ ********************************************************************* */
+static int umal_mii_probe(struct net_device *dev)
+{
+ struct umal_softc *sc = netdev_priv(dev);
+ struct phy_device *phy_dev;
+ int i;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ phy_dev = sc->mii_bus->phy_map[i];
+ if (phy_dev)
+ break;
+ }
+ if (!phy_dev) {
+ printk(KERN_ERR "%s: no PHY found\n", dev->name);
+ return -ENXIO;
+ }
+
+ phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &umal_miipoll, 0,
+ PHY_INTERFACE_MODE_MII);
+ if (IS_ERR(phy_dev)) {
+ printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
+ return PTR_ERR(phy_dev);
+ }
+
+ /* Remove any features not supported by the controller */
+ phy_dev->supported &= SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_MII;
+ phy_dev->advertising = phy_dev->supported;
+
+ pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+ dev->name, phy_dev->drv->name,
+ dev_name(&phy_dev->dev), phy_dev->irq);
+
+ sc->phy_dev = phy_dev;
+
+ return 0;
+}
+
+/**********************************************************************
+ * UMAL DMA functions
+ ********************************************************************* */
+
+/**********************************************************************
+ * UMALDMA_INITCTX(d,s,txrx,maxdescr)
+ *
+ * Initialize a DMA channel context. Since there are potentially
+ * eight DMA channels per MAC, it's nice to do this in a standard
+ * way.
+ *
+ * Input parameters:
+ * d - struct umaldma (DMA channel context)
+ * s - struct umal_softc (pointer to a MAC)
+ * txrx - Identifies DMA_TX or DMA_RX for channel direction
+ * maxdescr - number of descriptors
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umaldma_initctx(struct umaldma *d, struct umal_softc *s, int rxtx,
+ int maxdescr)
+{
+ struct umaldmadscr *dscr_item;
+ int idx;
+
+ /*
+ * Save away interesting stuff in the structure
+ */
+
+ d->umaldma_eth = s;
+ d->umaldma_txdir = rxtx;
+ d->umaldma_maxdescr = maxdescr;
+
+ /*
+ * Allocate memory for the ring
+ */
+
+ d->umaldma_dscrtable_unaligned = dma_alloc_coherent(NULL,
+ sizeof(*d->umaldma_dscrtable),
+ &d->umaldma_dscrtable_phys_unaligned,
+ GFP_KERNEL | GFP_DMA);
+
+ dma_cache_sync(NULL, d->umaldma_dscrtable_unaligned,
+ sizeof(*d->umaldma_dscrtable), DMA_BIDIRECTIONAL);
+
+ /*
+ * The descriptor table must be aligned to at least 16 bytes or the
+ * MAC will corrupt it.
+ */
+
+ d->umaldma_dscrtable = (struct umaldmadscr *)
+ ALIGN((unsigned long)d->umaldma_dscrtable_unaligned,
+ sizeof(*d->umaldma_dscrtable));
+
+ d->umaldma_dscrtable_end = d->umaldma_dscrtable + d->umaldma_maxdescr;
+
+ d->umaldma_dscrtable_phys = ALIGN((unsigned long)
+ d->umaldma_dscrtable_phys_unaligned,
+ sizeof(*d->umaldma_dscrtable));
+
+ for (idx = 0; idx < d->umaldma_maxdescr; idx++) {
+ dscr_item = d->umaldma_dscrtable + idx;
+ dscr_item->PacketStartAddr = 0;
+ dscr_item->PacketSize = UMAL_DESC_PACKETSIZE_EMPTY;
+ dscr_item->NextDescriptor = (dma_addr_t)(
+ (struct umaldmadscr *)d->umaldma_dscrtable_phys
+ + (idx+1));
+ dscr_item->NextDescriptor_Virt = d->umaldma_dscrtable + (idx+1);
+ }
+ dscr_item = d->umaldma_dscrtable +
+ (d->umaldma_maxdescr - 1);
+ dscr_item->NextDescriptor = d->umaldma_dscrtable_phys;
+ dscr_item->NextDescriptor_Virt = d->umaldma_dscrtable;
+
+ d->umaldma_addptr = d->umaldma_dscrtable;
+ d->umaldma_remptr = d->umaldma_dscrtable;
+
+ /*
+ * And context table
+ */
+
+ d->umaldma_ctxtable = kcalloc(d->umaldma_maxdescr,
+ sizeof(*d->umaldma_ctxtable), GFP_KERNEL);
+}
+
+/**********************************************************************
+ * UMALDMA_UNINITCTX(d)
+ *
+ * Uninitialize a DMA channel context.
+ *
+ * Input parameters:
+ * d - struct umaldma (DMA channel context)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umaldma_uninitctx(struct umaldma *d)
+{
+ if (d->umaldma_dscrtable_unaligned) {
+ dma_free_coherent(NULL,
+ sizeof(*d->umaldma_dscrtable),
+ d->umaldma_dscrtable_unaligned,
+ d->umaldma_dscrtable_phys_unaligned);
+ d->umaldma_dscrtable_unaligned = d->umaldma_dscrtable = NULL;
+ d->umaldma_dscrtable_phys_unaligned = 0;
+ d->umaldma_dscrtable_phys = 0;
+ }
+
+ kfree(d->umaldma_ctxtable);
+ d->umaldma_ctxtable = NULL;
+}
+
+/**********************************************************************
+ * UMALDMA_CHANNEL_START(d)
+ *
+ * Open a DMA channel.
+ *
+ * Input parameters:
+ * d - DMA channel to init (context must be previously init'd)
+ * rxtx - DMA_RX or DMA_TX depending on what type of channel
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umaldma_channel_start(struct umaldma *d, int rxtx)
+{
+ /*
+ * Turn on the DMA channel
+ */
+
+ if (rxtx == DMA_TX) {
+ UMAL_DMATxDescriptor = d->umaldma_dscrtable_phys;
+ UMAL_DMATxCtrl = UMAL_DMA_Enable;
+ } else {
+ UMAL_DMARxDescriptor = d->umaldma_dscrtable_phys;
+ UMAL_DMARxCtrl = UMAL_DMA_Enable;
+ }
+}
+
+/**********************************************************************
+ * UMALDMA_CHANNEL_STOP(d)
+ *
+ * Close DMA channel.
+ *
+ * Input parameters:
+ * d - DMA channel to init (context must be previously init'd
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umaldma_channel_stop(struct umaldma *d)
+{
+ /*
+ * Turn off the DMA channel
+ */
+
+ if (d->umaldma_txdir == DMA_TX) {
+ UMAL_DMATxCtrl = 0;
+ UMAL_DMATxDescriptor = 0;
+ } else {
+ UMAL_DMARxCtrl = 0;
+ UMAL_DMARxDescriptor = 0;
+ }
+
+ /*
+ * Zero ring pointers
+ */
+
+ d->umaldma_addptr = d->umaldma_dscrtable;
+ d->umaldma_remptr = d->umaldma_dscrtable;
+}
+
+/**********************************************************************
+ * UMALDMA_ADD_RCVBUFFER(d,sb)
+ *
+ * Add a buffer to the specified DMA channel.
+ * For receive channels, this queues a buffer for inbound packets.
+ *
+ * Input parameters:
+ * sc - softc structure
+ * d - DMA channel descriptor
+ * sb - sk_buff to add, or NULL if we should allocate one
+ *
+ * Return value:
+ * 0 if buffer could not be added (ring is full)
+ * 1 if buffer added successfully
+ ********************************************************************* */
+static int umaldma_add_rcvbuffer(struct umal_softc *sc, struct umaldma *d,
+ struct sk_buff *sb)
+{
+ struct net_device *dev = sc->umal_dev;
+ struct umaldmadscr *dsc;
+ struct umaldmadscr *nextdsc;
+ struct sk_buff *sb_new = NULL;
+
+ /* get pointer to our current place in the ring */
+
+ dsc = d->umaldma_addptr;
+ nextdsc = UMALDMA_NEXTBUF(d, umaldma_addptr);
+
+ /*
+ * figure out if the ring is full - if the next descriptor
+ * is the same as the one that we're going to remove from
+ * the ring, the ring is full
+ */
+
+ if (nextdsc == d->umaldma_remptr)
+ return -ENOSPC;
+
+ /*
+ * Allocate a sk_buff if we don't already have one.
+ * If we do have an sk_buff, reset it so that it's empty.
+ *
+ * Note: sk_buffs don't seem to be guaranteed to have any sort
+ * of alignment when they are allocated. Therefore, allocate enough
+ * extra space to make sure that:
+ *
+ * 1. the data does not start in the middle of a cache line.
+ * 2. The data does not end in the middle of a cache line
+ * 3. The buffer can be aligned such that the IP addresses are
+ * naturally aligned.
+ *
+ * Remember, the SOCs MAC writes whole cache lines at a time,
+ * without reading the old contents first. So, if the sk_buff's
+ * data portion starts in the middle of a cache line, the SOC
+ * DMA will trash the beginning (and ending) portions.
+ */
+
+ if (sb == NULL) {
+ sb_new = netdev_alloc_skb(dev, ENET_PACKET_SIZE +
+ SMP_CACHE_BYTES * 2 +
+ NET_IP_ALIGN);
+ if (sb_new == NULL) {
+ pr_info("%s: sk_buff allocation failed\n",
+ d->umaldma_eth->umal_dev->name);
+ return -ENOBUFS;
+ }
+ skb_reserve(sb_new, 2);
+ } else {
+ sb_new = sb;
+ /*
+ * nothing special to reinit buffer, it's already aligned
+ * and sb->data already points to a good place.
+ */
+ }
+
+ /*
+ * fill in the descriptor
+ */
+
+ dsc->PacketStartAddr = virt_to_phys(sb_new->data);
+ dsc->PacketSize = UMAL_DESC_PACKETSIZE_EMPTY;
+
+ /*
+ * fill in the context
+ */
+
+ d->umaldma_ctxtable[dsc-d->umaldma_dscrtable] = sb_new;
+
+ /*
+ * point at next packet
+ */
+
+ d->umaldma_addptr = nextdsc;
+
+ return 0; /* we did it */
+}
+
+/**********************************************************************
+ * UMALDMA_ADD_TXBUFFER(d,sb)
+ *
+ * Add a transmit buffer to the specified DMA channel, causing a
+ * transmit to start.
+ *
+ * Input parameters:
+ * d - DMA channel descriptor
+ * sb - sk_buff to add
+ *
+ * Return value:
+ * 0 transmit queued successfully
+ * otherwise error code
+ ********************************************************************* */
+static int umaldma_add_txbuffer(struct umaldma *d, struct sk_buff *sb)
+{
+ struct umaldmadscr *dsc;
+ struct umaldmadscr *nextdsc;
+
+ /* get pointer to our current place in the ring */
+
+ dsc = d->umaldma_addptr;
+ nextdsc = UMALDMA_NEXTBUF(d, umaldma_addptr);
+
+ /*
+ * figure out if the ring is full - if the next descriptor
+ * is the same as the one that we're going to remove from
+ * the ring, the ring is full
+ */
+ if (nextdsc == d->umaldma_remptr)
+ return -ENOSPC;
+
+ /*
+ * fill in the descriptor. Note that the number of cache
+ * blocks in the descriptor is the number of blocks
+ * *spanned*, so we need to add in the offset (if any)
+ * while doing the calculation.
+ */
+ dsc->PacketStartAddr = virt_to_phys(sb->data);
+ dsc->PacketSize = sb->len | UMAL_DESC_PACKETSIZE_NONEMPTY;
+
+ dma_map_single(NULL, sb->data, sb->len, DMA_BIDIRECTIONAL);
+ dma_cache_sync(NULL, sb->data, sb->len, DMA_BIDIRECTIONAL);
+
+ /*
+ * fill in the context
+ */
+ d->umaldma_ctxtable[dsc-d->umaldma_dscrtable] = sb;
+
+ /*
+ * point at next packet
+ */
+ d->umaldma_addptr = nextdsc;
+
+ return 0; /* we did it */
+}
+
+/**********************************************************************
+ * UMALDMA_EMPTYRING(d)
+ *
+ * Free all allocated sk_buffs on the specified DMA channel;
+ *
+ * Input parameters:
+ * d - DMA channel
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umaldma_emptyring(struct umaldma *d)
+{
+ int idx;
+ struct sk_buff *sb;
+
+ for (idx = 0; idx < d->umaldma_maxdescr; idx++) {
+ sb = d->umaldma_ctxtable[idx];
+ if (sb) {
+ dev_kfree_skb(sb);
+ d->umaldma_ctxtable[idx] = NULL;
+ }
+ }
+}
+
+/**********************************************************************
+ * UMALDMA_FILLRING(sc,d)
+ *
+ * Fill the specified DMA channel (must be receive channel)
+ * with sk_buffs
+ *
+ * Input parameters:
+ * sc - softc structure
+ * d - DMA channel
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umaldma_fillring(struct umal_softc *sc, struct umaldma *d)
+{
+ int idx;
+ for (idx = 0; idx < UMAL_MAX_RXDESCR - 1; idx++) {
+ if (umaldma_add_rcvbuffer(sc, d, NULL) != 0)
+ break;
+ }
+}
+
+/**********************************************************************
+ * UMALDMA_RX_PROCESS(sc,d,work_to_do,poll)
+ *
+ * Process "completed" receive buffers on the specified DMA channel.
+ *
+ * Input parameters:
+ * sc - softc structure
+ * d - DMA channel context
+ * work_to_do - no. of packets to process before enabling interrupt
+ * again (for NAPI)
+ * poll - 1: using polling (for NAPI)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static int umaldma_rx_process(struct umal_softc *sc, struct umaldma *d,
+ int work_to_do, int poll)
+{
+ struct net_device *dev = sc->umal_dev;
+ int curidx;
+ int hwidx;
+ struct umaldmadscr *dsc;
+ struct sk_buff *sb;
+ int len;
+ int work_done = 0;
+ int dropped = 0;
+ unsigned int int_status;
+
+ if (!netif_device_present(dev))
+ return 0;
+
+ int_status = UMAL_DMAInterrupt;
+
+ if (int_status & INT_RX_BUS_ERR) {
+ UMAL_DMARxStatus = CLR_RX_BUS_ERR;
+ UMAL_DMARxCtrl |= UMAL_DMA_Enable;
+ }
+
+ if (int_status & INT_RX_OVERFLOW) {
+ UMAL_DMARxStatus = CLR_RX_OVERFLOW;
+ UMAL_DMARxCtrl |= UMAL_DMA_Enable;
+ }
+
+ if (int_status & INT_RX_PKT) {
+ while (work_to_do-- > 0) {
+
+ /*
+ * figure out where we are (as an index) and where
+ * the hardware is (also as an index)
+ *
+ * This could be done faster if (for example) the
+ * descriptor table was page-aligned and contiguous in
+ * both virtual and physical memory -- you could then
+ * just compare the low-order bits of the virtual
+ * address (sbdma_remptr) and the physical address
+ * (sbdma_curdscr CSR)
+ */
+
+ dsc = d->umaldma_remptr;
+ curidx = dsc - d->umaldma_dscrtable;
+
+ hwidx = (struct umaldmadscr *)UMAL_DMARxDescriptor -
+ (struct umaldmadscr *)d->umaldma_dscrtable_phys;
+
+ UMAL_DMARxStatus = CLR_RX_PKT;
+
+ /*
+ * If they're the same, that means we've processed all
+ * of the descriptors up to (but not including) the one
+ * that the hardware is working on right now.
+ */
+ if (curidx == hwidx)
+ goto done;
+
+ /*
+ * Otherwise, get the packet's sk_buff ptr back
+ */
+ sb = d->umaldma_ctxtable[curidx];
+ len = dsc->PacketSize & 0xfff;
+ d->umaldma_ctxtable[curidx] = NULL;
+
+ /*
+ * .. and advance to the next buffer.
+ */
+ d->umaldma_remptr = UMALDMA_NEXTBUF(d, umaldma_remptr);
+
+ /*
+ * Check packet status. If good, process it.
+ * If not, silently drop it and put it back on the
+ * receive ring.
+ */
+ if (likely(!(dsc->PacketSize &
+ UMAL_DESC_PACKETSIZE_EMPTY))) {
+ /*
+ * Add a new buffer to replace the old one.
+ * If we fail to allocate a buffer, we're going
+ * to drop this packet and put it right back on
+ * the receive ring.
+ */
+ if (unlikely(umaldma_add_rcvbuffer(sc, d, NULL)
+ == -ENOBUFS)) {
+ dev->stats.rx_dropped++;
+ /* Re-add old buffer */
+ umaldma_add_rcvbuffer(sc, d, sb);
+ /* No point in continuing */
+ printk(KERN_ERR "dropped packet (1)\n");
+ d->umaldma_remptr = UMALDMA_NEXTBUF(d,
+ umaldma_remptr);
+ goto done;
+ } else {
+ /*
+ * Set length into the packet
+ */
+ skb_put(sb, len + 4);
+
+ /*
+ * Buffer has been replaced on the
+ * receive ring. Pass the buffer to
+ * the kernel
+ */
+ sb->protocol = eth_type_trans(sb,
+ d->umaldma_eth->umal_dev);
+ /*
+ * Check hw IPv4/TCP checksum
+ * if supported
+ */
+ skb_checksum_none_assert(sb);
+
+ if (poll)
+ dropped = netif_receive_skb(sb);
+ else
+ dropped = netif_rx(sb);
+
+ if (dropped == NET_RX_DROP) {
+ dev->stats.rx_dropped++;
+ d->umaldma_remptr =
+ UMALDMA_NEXTBUF(d,
+ umaldma_remptr);
+ goto done;
+ } else {
+ dev->stats.rx_bytes += len;
+ dev->stats.rx_packets++;
+ }
+ }
+ } else {
+ /*
+ * Packet was mangled somehow. Just drop it and
+ * put it back on the receive ring.
+ */
+ dev->stats.rx_errors++;
+ umaldma_add_rcvbuffer(sc, d, sb);
+ }
+ work_done++;
+ }
+ }
+done:
+ return work_done;
+}
+
+/**********************************************************************
+ * UMALDMA_TX_PROCESS(sc,d,poll)
+ *
+ * Process "completed" transmit buffers on the specified DMA channel.
+ * This is normally called within the interrupt service routine.
+ * Note that this isn't really ideal for priority channels, since
+ * it processes all of the packets on a given channel before
+ * returning.
+ *
+ * Input parameters:
+ * sc - softc structure
+ * d - DMA channel context
+ * poll - 1: using polling (for NAPI)
+ *
+ * Return value:
+ * nothing
+ **********************************************************************/
+static void umaldma_tx_process(struct umal_softc *sc, struct umaldma *d,
+ int poll)
+{
+ struct net_device *dev = sc->umal_dev;
+ int curidx;
+ int hwidx;
+ struct umaldmadscr *dsc;
+ struct sk_buff *sb;
+ unsigned long flags;
+ int packets_handled = 0;
+ unsigned int int_status;
+
+ spin_lock_irqsave(&(sc->umal_lock), flags);
+
+ if (!netif_device_present(dev))
+ return;
+
+ int_status = UMAL_DMAInterrupt;
+
+
+ if (int_status & INT_TX_BUS_ERR)
+ UMAL_DMATxStatus = CLR_TX_BUS_ERR;
+
+ if (int_status & INT_TX_UNDERRUN)
+ UMAL_DMATxStatus = CLR_TX_UNDERRUN;
+
+ if (int_status & INT_TX_PKT) {
+ hwidx = (struct umaldmadscr *)UMAL_DMATxDescriptor -
+ (struct umaldmadscr *)d->umaldma_dscrtable_phys;
+
+ if (d->umaldma_remptr == d->umaldma_addptr)
+ goto end_unlock;
+
+ for (;;) {
+ /*
+ * figure out where we are (as an index) and where
+ * the hardware is (also as an index)
+ *
+ * This could be done faster if (for example) the
+ * descriptor table was page-aligned and contiguous in
+ * both virtual and physical memory -- you could then
+ * just compare the low-order bits of the virtual
+ * address (sbdma_remptr) and the physical address
+ * (sbdma_curdscr CSR)
+ */
+ curidx = d->umaldma_remptr - d->umaldma_dscrtable;
+
+ /*
+ * If they're the same, that means we've processed all
+ * of the descriptors up to (but not including) the one
+ * that the hardware is working on right now.
+ */
+ if (curidx == hwidx)
+ break;
+
+ /*
+ * Otherwise, get the packet's sk_buff ptr back
+ */
+ dsc = &(d->umaldma_dscrtable[curidx]);
+ sb = d->umaldma_ctxtable[curidx];
+
+ /*
+ * Stats
+ */
+ dev->stats.tx_bytes += sb->len;
+ dev->stats.tx_packets++;
+
+ /*
+ * for transmits, we just free buffers.
+ */
+ dev_kfree_skb_irq(sb);
+ d->umaldma_ctxtable[curidx] = NULL;
+ UMAL_DMATxStatus = CLR_TX_PKT;
+
+ /*
+ * .. and advance to the next buffer.
+ */
+ d->umaldma_remptr = UMALDMA_NEXTBUF(d, umaldma_remptr);
+ packets_handled++;
+ }
+
+ /*
+ * Decide if we should wake up the protocol or not.
+ * Other drivers seem to do this when we reach a low
+ * watermark on the transmit queue.
+ */
+ if (packets_handled)
+ netif_wake_queue(d->umaldma_eth->umal_dev);
+ }
+
+end_unlock:
+ spin_unlock_irqrestore(&(sc->umal_lock), flags);
+}
+
+/**********************************************************************
+ * UMAL Channel functions
+ ********************************************************************* */
+
+/**********************************************************************
+ * UMAL_INITCTX(s)
+ *
+ * Initialize an Ethernet context structure - this is called
+ * once per MAC. Memory is allocated here, so don't
+ * call it again from inside the ioctl routines that bring the
+ * interface up/down
+ *
+ * Input parameters:
+ * s - umal context structure
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+static int umal_initctx(struct umal_softc *s)
+{
+ /*
+ * Initialize the DMA channels.
+ * Note: Only do this _once_, as it allocates memory from the kernel!
+ */
+
+ umaldma_initctx(&(s->umal_txdma), s, DMA_TX, UMAL_MAX_TXDESCR);
+ umaldma_initctx(&(s->umal_rxdma), s, DMA_RX, UMAL_MAX_RXDESCR);
+
+ /*
+ * initial state is OFF
+ */
+
+ s->umal_state = umal_state_off;
+
+ return 0;
+}
+
+/**********************************************************************
+ * UMAL_UNINITCTX(s)
+ *
+ * Initialize an Ethernet context structure - this is called
+ * once per MAC on the 1250. Memory is allocated here, so don't
+ * call it again from inside the ioctl routines that bring the
+ * interface up/down
+ *
+ * Input parameters:
+ * s - umal context structure
+ *
+ * Return value:
+ * Nothing
+ ********************************************************************* */
+static void umal_uninitctx(struct umal_softc *s)
+{
+ umaldma_uninitctx(&(s->umal_txdma));
+ umaldma_uninitctx(&(s->umal_rxdma));
+}
+
+/**********************************************************************
+ * UMAL_CHANNEL_START(s)
+ *
+ * Start packet processing on this MAC.
+ *
+ * Input parameters:
+ * s - umal context structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umal_channel_start(struct umal_softc *s)
+{
+ /*
+ * Don't do this if running
+ */
+ if (s->umal_state == umal_state_on)
+ return;
+
+ /* don't accept any packets, disable all interrupts */
+ umaldma_channel_stop(&(s->umal_rxdma));
+ umaldma_channel_stop(&(s->umal_txdma));
+
+ UMAL_DMAIntrMask = 0;
+ umal_clr_intr(s->umal_dev);
+
+ /*
+ * Program the hardware address. It goes into the hardware-address
+ * register as well as the first filter register.
+ */
+ UMAL_STADDR1 = s->umal_hwaddr[0]<<24 | s->umal_hwaddr[1]<<16 |
+ s->umal_hwaddr[2]<<8 | s->umal_hwaddr[3];
+ UMAL_STADDR2 = s->umal_hwaddr[4]<<24 | s->umal_hwaddr[5]<<16;
+
+ /*
+ * Configure the speed, duplex, and flow control
+ */
+ umal_set_speed(s, s->umal_speed);
+ umal_set_duplex(s, s->umal_duplex, s->umal_fc);
+
+ /*
+ * Program multicast addresses
+ */
+ umal_setmulti(s);
+
+ /*
+ * If channel was in promiscuous mode before, turn that on
+ */
+ if (s->umal_devflags & IFF_PROMISC)
+ umal_promiscuous_mode(s, 1);
+
+ /*
+ * Fill the receive ring
+ */
+ umaldma_fillring(s, &(s->umal_rxdma));
+
+ umaldma_channel_start(&(s->umal_rxdma), DMA_RX);
+ umaldma_channel_start(&(s->umal_txdma), DMA_TX);
+
+ s->umal_state = umal_state_on;
+
+ /*
+ * Initialize DMA channels (rings should be ok now)
+ */
+ UMAL_DMAIntrMask = INT_RX_BUS_ERR | INT_RX_OVERFLOW |
+ INT_RX_PKT | INT_TX_BUS_ERR |
+ INT_TX_UNDERRUN | INT_TX_PKT |
+ UMAL_DMAIntrMask_ENABLEHALFWORD;
+
+ /*
+ * we're running now.
+ */
+ UMAL_CFG1 |= UMAL_CFG1_RXENABLE | UMAL_CFG1_TXENABLE;
+}
+
+/**********************************************************************
+ * UMAL_CHANNEL_STOP(s)
+ *
+ * Stop packet processing on this MAC.
+ *
+ * Input parameters:
+ * s - umal context structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umal_channel_stop(struct umal_softc *s)
+{
+ /* don't do this if already stopped */
+ if (s->umal_state == umal_state_off)
+ return;
+
+ /* don't accept any packets, disable all interrupts */
+ UMAL_DMAIntrMask = 0;
+ umal_clr_intr(s->umal_dev);
+
+ /* turn off receiver and transmitter */
+ UMAL_CFG1 = UMAL_CFG1_RESET; /* reset MAC */
+ UMAL_CFG1 = 0;
+
+ /* We're stopped now. */
+ s->umal_state = umal_state_off;
+
+ /*
+ * Stop DMA channels (rings should be ok now)
+ */
+ umaldma_channel_stop(&(s->umal_rxdma));
+ umaldma_channel_stop(&(s->umal_txdma));
+
+ /* Empty the receive and transmit rings */
+ umaldma_emptyring(&(s->umal_rxdma));
+ umaldma_emptyring(&(s->umal_txdma));
+}
+
+/**********************************************************************
+ * UMAL_SET_CHANNEL_STATE(s,state)
+ *
+ * Set the channel's state ON or OFF
+ *
+ * Input parameters:
+ * s - umal context structure
+ * state - new state
+ *
+ * Return value:
+ * old state
+ ********************************************************************* */
+static enum umal_state umal_set_channel_state(struct umal_softc *s,
+ enum umal_state state)
+{
+ enum umal_state oldstate = s->umal_state;
+
+ /*
+ * If same as previous state, return
+ */
+ if (state == oldstate)
+ return oldstate;
+
+ /*
+ * If new state is ON, turn channel on
+ */
+ if (state == umal_state_on)
+ umal_channel_start(s);
+ else
+ umal_channel_stop(s);
+
+ /*
+ * Return previous state
+ */
+ return oldstate;
+}
+
+/**********************************************************************
+ * UMAL functions
+ ********************************************************************* */
+static const struct net_device_ops umal_netdev_ops = {
+ .ndo_open = umal_open,
+ .ndo_stop = umal_close,
+ .ndo_start_xmit = umal_start_tx,
+ .ndo_set_multicast_list = umal_set_rx_mode,
+ .ndo_tx_timeout = umal_tx_timeout,
+ .ndo_do_ioctl = umal_mii_ioctl,
+ .ndo_change_mtu = umal_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
+};
+
+/**********************************************************************
+ * UMAL_INIT(dev)
+ *
+ * Attach routine - init hardware and hook ourselves into linux
+ *
+ * Input parameters:
+ * dev - net_device structure
+ *
+ * Return value:
+ * 0 if ok
+ ********************************************************************* */
+static int umal_init(struct platform_device *pldev, long long base)
+{
+ struct net_device *dev = dev_get_drvdata(&pldev->dev);
+ int idx = pldev->id;
+ struct umal_softc *sc = netdev_priv(dev);
+ unsigned char *eaddr;
+ int i;
+ int err;
+
+ sc->umal_dev = dev;
+ sc->umal_idx = idx;
+
+ eaddr = sc->umal_hwaddr;
+#ifdef CONFIG_CMDLINE_FORCE
+ for (i = 0; i < 6; i++)
+ eaddr[i] = hw_addr[0].addr[i];
+#endif
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = eaddr[i];
+
+ /*
+ * Set up Linux device callins
+ */
+
+ spin_lock_init(&(sc->umal_lock));
+
+ dev->netdev_ops = &umal_netdev_ops;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ dev->irq = IRQ_UMAL;
+
+ sc->mii_bus = mdiobus_alloc();
+ if (sc->mii_bus == NULL) {
+ err = -ENOMEM;
+ goto uninit_ctx;
+ }
+
+ sc->mii_bus->name = umal_mdio_string;
+ snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx);
+ sc->mii_bus->priv = sc;
+ sc->mii_bus->read = umal_mii_read;
+ sc->mii_bus->write = umal_mii_write;
+ sc->mii_bus->reset = umal_mii_reset;
+ sc->mii_bus->irq = sc->phy_irq;
+ for (i = 0; i < PHY_MAX_ADDR; ++i)
+ sc->mii_bus->irq[i] = PHY_POLL;
+
+ sc->mii_bus->parent = &pldev->dev;
+
+ /*
+ * Probe PHY address
+ */
+ err = mdiobus_register(sc->mii_bus);
+ if (err) {
+ printk(KERN_ERR "%s: unable to register MDIO bus\n",
+ dev->name);
+ goto free_mdio;
+ }
+ dev_set_drvdata(&pldev->dev, sc->mii_bus);
+
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR "%s.%d: unable to register netdev\n",
+ umal_string, idx);
+ goto unreg_mdio;
+ }
+
+ pr_info("%s.%d: registered as %s\n", umal_string, idx, dev->name);
+
+ /*
+ * Initialize context (get pointers to registers and stuff), then
+ * allocate the memory for the descriptor tables.
+ */
+ dev->dev.coherent_dma_mask = 0xFFFFFFFF;
+ umal_initctx(sc);
+
+ /*
+ * Display Ethernet address (this is called during the config
+ * process so we need to finish off the config message that
+ * was being displayed)
+ */
+ pr_info("%s: UMAL Ethernet at 0x%08Lx, address: %pM\n",
+ dev->name, base, eaddr);
+
+ return 0;
+unreg_mdio:
+ mdiobus_unregister(sc->mii_bus);
+ dev_set_drvdata(&pldev->dev, NULL);
+free_mdio:
+ mdiobus_free(sc->mii_bus);
+uninit_ctx:
+ umal_uninitctx(sc);
+ return err;
+}
+
+/**********************************************************************
+ * UMAL_OPEN(dev)
+ *
+ * Open umal device
+ *
+ * Input parameters:
+ * dev - net_device structure
+ *
+ * Return value:
+ * 0 if ok
+ * otherwise error
+ ********************************************************************* */
+static int umal_open(struct net_device *dev)
+{
+ struct umal_softc *sc = netdev_priv(dev);
+ int err;
+
+ sc->umal_speed = umal_speed_none;
+ sc->umal_duplex = umal_duplex_none;
+ sc->umal_fc = umal_fc_none;
+ sc->umal_pause = -1;
+ sc->umal_link = 0;
+
+ /* reset mac and interface */
+ UMAL_CFG1 = UMAL_CFG1_RESET; /* reset MAC */
+ UMAL_CFG1 = 0; /* clear the reset bit of MAC */
+ UMAL_IFCTRL = UMAL_IFCTRL_RESET; /* reset the MAC Interface */
+ UMAL_DMAIntrMask = 0;
+
+ /*
+ * Attach to the PHY
+ */
+ err = umal_mii_probe(dev);
+ if (err)
+ goto out_unregister;
+
+ /*
+ * Turn on the channel
+ */
+ phy_start(sc->phy_dev);
+
+ /* config fifo */
+ UMAL_FIFOCFG0 = 0x000000ff; /* reset FIFO */
+ UMAL_FIFOCFG1 = 0x0fff0fff; /* request enable modules in fifo */
+ UMAL_FIFOCFG2 = 0x0aaa0555; /* request enable modules in fifo */
+ UMAL_FIFOCFG3 = 0x02800fff; /* set water mark register */
+ UMAL_FIFOCFG4 = 0x00000070;
+ UMAL_FIFOCFG5 = 0x0007ff8f;
+ UMAL_FIFOCFG0 = 0x0000ff00; /* request enable modules in fifo */
+
+ UMAL_CFG2 = 0x7016;
+
+ /*
+ * map/route interrupt (clear status first, in case something
+ * weird is pending; we haven't initialized the mac registers
+ * yet)
+ */
+ umal_clr_intr(dev);
+
+ err = request_irq(dev->irq, umal_intr, IRQF_SHARED, dev->name, dev);
+ if (err) {
+ printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name,
+ dev->irq);
+ goto out_err;
+ }
+
+ umal_set_channel_state(sc, umal_state_on);
+
+ netif_start_queue(dev);
+
+ umal_set_rx_mode(dev);
+
+ return 0;
+
+out_unregister:
+ free_irq(dev->irq, dev);
+out_err:
+ return err;
+}
+
+/**********************************************************************
+ * UMAL_CLSOE(dev)
+ *
+ * Close umal device
+ *
+ * Input parameters:
+ * dev - net_device structure
+ *
+ * Return value:
+ * 0 if ok
+ ********************************************************************* */
+static int umal_close(struct net_device *dev)
+{
+ struct umal_softc *sc = netdev_priv(dev);
+
+ phy_stop(sc->phy_dev);
+
+ umal_set_channel_state(sc, umal_state_off);
+
+ netif_stop_queue(dev);
+
+ phy_disconnect(sc->phy_dev);
+ sc->phy_dev = NULL;
+
+ free_irq(dev->irq, dev);
+
+ umaldma_emptyring(&(sc->umal_rxdma));
+ umaldma_emptyring(&(sc->umal_txdma));
+
+ return 0;
+}
+
+/**********************************************************************
+ * UMAL_MII_IOCTL(dev,rq,cmd)
+ *
+ * Umal device ioctrl routine
+ *
+ * Input parameters:
+ * dev - net_device structure
+ * rq - interface request structure
+ * cmd - ioctrl command
+ *
+ * Return value:
+ * ioctrl command result
+ ********************************************************************* */
+static int umal_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct umal_softc *sc = netdev_priv(dev);
+
+ if (!netif_running(dev) || !sc->phy_dev)
+ return -EINVAL;
+
+ return phy_mii_ioctl(sc->phy_dev, rq, cmd);
+}
+
+/**********************************************************************
+ * UMAL_INTR(irq,dev_instance)
+ *
+ * Interrupt handler for MAC interrupts
+ *
+ * Input parameters:
+ * irq - irq number
+ * dev_instance - net_device structure
+ *
+ * Return value:
+ * irq handling result
+ ********************************************************************* */
+static irqreturn_t umal_intr(int irq, void *dev_instance)
+{
+ struct net_device *dev = (struct net_device *) dev_instance;
+ struct umal_softc *sc = netdev_priv(dev);
+ uint64_t isr;
+ int handled = 0;
+
+ /*
+ * Read the ISR (this clears the bits in the real
+ * register, except for counter addr)
+ */
+ isr = UMAL_DMAInterrupt;
+ if (isr == 0)
+ return IRQ_RETVAL(0);
+
+ if (sc->umal_state != umal_state_on) {
+ umal_clr_intr(dev);
+ return IRQ_RETVAL(0);
+ }
+ handled = 1;
+
+ /*
+ * Transmits on channel 0
+ */
+ if (isr & INT_TX_MASK)
+ umaldma_tx_process(sc, &(sc->umal_txdma), 0);
+ if (isr & INT_RX_MASK)
+ umaldma_rx_process(sc, &(sc->umal_rxdma),
+ UMAL_MAX_RXDESCR * 2, 0);
+
+ return IRQ_RETVAL(handled);
+}
+
+/**********************************************************************
+ * UMAL_CLR_INTR(dev)
+ *
+ * Clear all interrupt of umal
+ *
+ * Input parameters:
+ * dev - net_device structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umal_clr_intr(struct net_device *dev)
+{
+ unsigned int int_status;
+
+ if (!netif_device_present(dev))
+ return;
+ int_status = UMAL_DMAInterrupt;
+ if (int_status & INT_RX_PKT)
+ UMAL_DMARxStatus = CLR_RX_PKT;
+
+ if (int_status & INT_RX_BUS_ERR)
+ UMAL_DMARxStatus = CLR_RX_BUS_ERR;
+
+ if (int_status & INT_RX_OVERFLOW)
+ UMAL_DMARxStatus = CLR_RX_OVERFLOW;
+
+ if (int_status & INT_TX_PKT)
+ UMAL_DMATxStatus = CLR_TX_PKT;
+
+ if (int_status & INT_TX_BUS_ERR)
+ UMAL_DMATxStatus = CLR_TX_BUS_ERR;
+
+ if (int_status & INT_TX_UNDERRUN)
+ UMAL_DMATxStatus = CLR_TX_UNDERRUN;
+}
+
+/**********************************************************************
+ * UMAL_START_TX(skb,dev)
+ *
+ * Start output on the specified interface. Basically, we
+ * queue as many buffers as we can until the ring fills up, or
+ * we run off the end of the queue, whichever comes first.
+ *
+ * Input parameters:
+ * skb - sk_buff structure
+ * dev - net_device structure
+ *
+ * Return value:
+ * 0 if ok
+ * otherwise error
+ ********************************************************************* */
+static int umal_start_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct umal_softc *sc = netdev_priv(dev);
+ unsigned long flags;
+
+ /* lock eth irq */
+ spin_lock_irqsave(&sc->umal_lock, flags);
+
+ /*
+ * Put the buffer on the transmit ring. If we
+ * don't have room, stop the queue.
+ */
+ if (umaldma_add_txbuffer(&(sc->umal_txdma), skb)) {
+ /* XXX save skb that we could not send */
+ netif_stop_queue(dev);
+ spin_unlock_irqrestore(&sc->umal_lock, flags);
+
+ return NETDEV_TX_BUSY;
+ }
+
+ UMAL_CFG1 |= UMAL_CFG1_TXENABLE;
+ UMAL_DMATxCtrl |= UMAL_DMA_Enable;
+
+ spin_unlock_irqrestore(&sc->umal_lock, flags);
+
+ return 0;
+}
+
+/**********************************************************************
+ * UMAL_TX_TIMEOUT(dev)
+ *
+ * Tx timeout, update statistic structure
+ *
+ * Input parameters:
+ * dev - net_device structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umal_tx_timeout(struct net_device *dev)
+{
+ struct umal_softc *sc = netdev_priv(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&sc->umal_lock, flags);
+
+ dev->trans_start = jiffies; /* prevent tx timeout */
+ dev->stats.tx_errors++;
+
+ spin_unlock_irqrestore(&sc->umal_lock, flags);
+
+ printk(KERN_WARNING "%s: Transmit timed out\n", dev->name);
+}
+
+/**********************************************************************
+ * UMAL_SET_RX_MODE(dev)
+ *
+ * Set promiscuous mode and multicast list
+ *
+ * Input parameters:
+ * dev - net_device structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umal_set_rx_mode(struct net_device *dev)
+{
+ unsigned long flags;
+ struct umal_softc *sc = netdev_priv(dev);
+
+ spin_lock_irqsave(&sc->umal_lock, flags);
+ if ((dev->flags ^ sc->umal_devflags) & IFF_PROMISC) {
+ /*
+ * Promiscuous changed.
+ */
+ if (dev->flags & IFF_PROMISC)
+ umal_promiscuous_mode(sc, 1);
+ else
+ umal_promiscuous_mode(sc, 0);
+ }
+ spin_unlock_irqrestore(&sc->umal_lock, flags);
+
+ /*
+ * Program the multicasts. Do this every time.
+ */
+ umal_setmulti(sc);
+}
+
+/**********************************************************************
+ * UMAL_PROMISCUOUS_MODE(sc,onoff)
+ *
+ * Turn on or off promiscuous mode
+ *
+ * Input parameters:
+ * sc - softc
+ * onoff - 1 to turn on, 0 to turn off
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umal_promiscuous_mode(struct umal_softc *sc, int onoff)
+{
+ if (onoff) {
+ UMAL_FIFOCFG4 &= ~0x40000;
+ UMAL_FIFOCFG5 |= 0x40000;
+ } else {
+ UMAL_FIFOCFG4 |= 0x40000;
+ UMAL_FIFOCFG5 &= ~0x40000;
+ }
+}
+
+/**********************************************************************
+ * UMAL_SETMULTI(sc)
+ *
+ * Reprogram the multicast table into the hardware, given
+ * the list of multicasts associated with the interface
+ * structure.
+ *
+ * Input parameters:
+ * sc - softc
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umal_setmulti(struct umal_softc *sc)
+{
+}
+
+/**********************************************************************
+ * UMAL_SET_SPEED(s,speed)
+ *
+ * Configure LAN speed for the specified MAC.
+ * Warning: must be called when MAC is off!
+ *
+ * Input parameters:
+ * s - sbmac structure
+ * speed - speed to set MAC to (see enum sbmac_speed)
+ *
+ * Return value:
+ * 1 if successful
+ * 0 indicates invalid parameters
+ ********************************************************************* */
+static int umal_set_speed(struct umal_softc *s, enum umal_speed speed)
+{
+ unsigned int cfg;
+
+ /*
+ * Save new current values
+ */
+ s->umal_speed = speed;
+
+ if (s->umal_state == umal_state_on)
+ return 0; /* save for next restart */
+
+ /*
+ * Read current register values
+ */
+ cfg = UMAL_CFG2;
+
+ /*
+ * Mask out the stuff we want to change
+ */
+ cfg &= ~(UMAL_CFG2_MODEMASK);
+
+ /*
+ * Now add in the new bits
+ */
+ switch (speed) {
+ case umal_speed_10:
+ cfg |= UMAL_CFG2_NIBBLEMODE;
+ break;
+
+ case umal_speed_100:
+ cfg |= UMAL_CFG2_NIBBLEMODE;
+ break;
+
+ default:
+ return 0;
+ }
+
+ /*
+ * Send the bits back to the hardware
+ */
+ UMAL_CFG2 = cfg;
+
+ return 1;
+}
+
+/**********************************************************************
+ * UMAL_SET_DUPLEX(s,duplex,fc)
+ *
+ * Set Ethernet duplex and flow control options for this MAC
+ * Warning: must be called when MAC is off!
+ *
+ * Input parameters:
+ * s - umal structure
+ * duplex - duplex setting (see enum sbmac_duplex)
+ * fc - flow control setting (see enum sbmac_fc)
+ *
+ * Return value:
+ * 1 if ok
+ * 0 if an invalid parameter combination was specified
+ ********************************************************************* */
+static int umal_set_duplex(struct umal_softc *s, enum umal_duplex duplex,
+ enum umal_fc fc)
+{
+ unsigned int cfg1, cfg2;
+ int err = 0;
+
+ /*
+ * Save new current values
+ */
+ s->umal_duplex = duplex;
+ s->umal_fc = fc;
+
+ if (s->umal_state == umal_state_on)
+ return 0; /* save for next restart */
+
+ /*
+ * Read current register values
+ */
+ cfg1 = UMAL_CFG1;
+ cfg2 = UMAL_CFG2;
+
+ /*
+ * Mask off the stuff we're about to change
+ */
+ cfg1 &= ~(UMAL_CFG1_TXFLOWCTL | UMAL_CFG1_RXFLOWCTL);
+ cfg2 &= ~(UMAL_CFG2_FULLDUPLEX);
+
+ err = 0;
+ switch (duplex) {
+ case umal_duplex_half:
+ break;
+
+ case umal_duplex_full:
+ cfg2 |= UMAL_CFG2_FULLDUPLEX;
+ break;
+
+ default:
+ err = 1;
+ }
+ if (!err)
+ UMAL_CFG2 = cfg2;
+
+ err = 0;
+ switch (fc) {
+ case umal_fc_disabled:
+ break;
+
+ case umal_fc_collision:
+ break;
+
+ case umal_fc_carrier:
+ break;
+
+ case umal_fc_frame:
+ cfg1 |= UMAL_CFG1_TXFLOWCTL | UMAL_CFG1_RXFLOWCTL;
+ break;
+
+ default:
+ err = 1;
+ }
+
+ if (!err)
+ UMAL_CFG1 = cfg1;
+
+ /*
+ * Send the bits back to the hardware
+ */
+ return 1;
+}
+
+/**********************************************************************
+ * UMAL_CHANGE_MTU(dev,new_mtu)
+ *
+ * Change MTU value
+ *
+ * Input parameters:
+ * dev - net_device structure
+ * new_mtu - new mtu value
+ *
+ * Return value:
+ * 1 if ok
+ ********************************************************************* */
+static int umal_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if (new_mtu > ENET_PACKET_SIZE)
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+
+ pr_info("changing the mtu to %d\n", new_mtu);
+
+ return 0;
+}
+
+/**********************************************************************
+ * UMAL_MIIPOLL(dev)
+ *
+ * Phy statemachine call back routine for link change
+ *
+ * Input parameters:
+ * dev - net_device structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void umal_miipoll(struct net_device *dev)
+{
+ struct umal_softc *sc = netdev_priv(dev);
+ struct phy_device *phy_dev = sc->phy_dev;
+ unsigned long flags;
+ enum umal_fc fc;
+ int link_chg, speed_chg, duplex_chg, pause_chg, fc_chg;
+
+ link_chg = (sc->umal_link != phy_dev->link);
+ speed_chg = (sc->umal_speed != phy_dev->speed);
+ duplex_chg = (sc->umal_duplex != phy_dev->duplex);
+ pause_chg = (sc->umal_pause != phy_dev->pause);
+
+ if (!link_chg && !speed_chg && !duplex_chg && !pause_chg)
+ return; /* Hmmm... */
+
+ if (!phy_dev->link) {
+ if (link_chg) {
+ sc->umal_link = phy_dev->link;
+ sc->umal_speed = umal_speed_none;
+ sc->umal_duplex = umal_duplex_none;
+ sc->umal_fc = umal_fc_disabled;
+ sc->umal_pause = -1;
+ pr_info("%s: link unavailable\n", dev->name);
+ }
+ return;
+ }
+
+ if (phy_dev->duplex == DUPLEX_FULL) {
+ if (phy_dev->pause)
+ fc = umal_fc_frame;
+ else
+ fc = umal_fc_disabled;
+ } else
+ fc = umal_fc_collision;
+ fc_chg = (sc->umal_fc != fc);
+
+ pr_info("%s: link available: %dbase-%cD\n", dev->name, phy_dev->speed,
+ phy_dev->duplex == DUPLEX_FULL ? 'F' : 'H');
+
+ spin_lock_irqsave(&sc->umal_lock, flags);
+
+ sc->umal_speed = phy_dev->speed;
+ sc->umal_duplex = phy_dev->duplex;
+ sc->umal_fc = fc;
+ sc->umal_pause = phy_dev->pause;
+ sc->umal_link = phy_dev->link;
+
+ if ((speed_chg || duplex_chg || fc_chg) &&
+ sc->umal_state != umal_state_off) {
+ /*
+ * something changed, restart the channel
+ */
+ umal_channel_stop(sc);
+ umal_channel_start(sc);
+ }
+
+ spin_unlock_irqrestore(&sc->umal_lock, flags);
+}
+
+static int umal_probe(struct platform_device *pldev)
+{
+ struct net_device *dev;
+ struct umal_softc *sc;
+ struct resource *res;
+ int err;
+
+ res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+ BUG_ON(!res);
+
+ /*
+ * Okay, cool. Initialize this MAC.
+ */
+ dev = alloc_etherdev(sizeof(struct umal_softc));
+ if (!dev) {
+ printk(KERN_ERR "%s: unable to allocate etherdev\n",
+ dev_name(&pldev->dev));
+ err = -ENOMEM;
+ goto out_out;
+ }
+
+ dev_set_drvdata(&pldev->dev, dev);
+ SET_NETDEV_DEV(dev, &pldev->dev);
+
+ sc = netdev_priv(dev);
+
+ err = umal_init(pldev, res->start);
+ if (err)
+ goto out_kfree;
+
+ return 0;
+
+out_kfree:
+ free_netdev(dev);
+
+out_out:
+ return err;
+}
+
+static int __exit umal_remove(struct platform_device *pldev)
+{
+ struct net_device *dev = dev_get_drvdata(&pldev->dev);
+ struct umal_softc *sc = netdev_priv(dev);
+
+ unregister_netdev(dev);
+ umal_uninitctx(sc);
+ mdiobus_unregister(sc->mii_bus);
+ free_netdev(dev);
+
+ return 0;
+}
+
+#if CONFIG_PM
+static void umal_reset(struct net_device *ndev)
+{
+ UMAL_CFG1 = UMAL_CFG1_RESET; /* reset MAC */
+ UMAL_CFG1 = 0; /* clear the reset bit of MAC */
+ UMAL_IFCTRL = UMAL_IFCTRL_RESET; /* reset the MAC Interface */
+ UMAL_DMAIntrMask = 1;
+
+ UMAL_FIFOCFG0 = 0x000000ff; /* reset FIFO */
+ UMAL_FIFOCFG1 = 0x0fff0fff; /* request enable modules in fifo */
+ UMAL_FIFOCFG2 = 0x0aaa0555; /* request enable modules in fifo */
+ UMAL_FIFOCFG3 = 0x02800fff; /* set water mark register */
+ UMAL_FIFOCFG4 = 0x00000070;
+ UMAL_FIFOCFG5 = 0x0007ff8f;
+ UMAL_FIFOCFG0 = 0x0000ff00; /* request enable modules in fifo */
+
+ UMAL_CFG2 = 0x7016;
+}
+
+static void umal_shutdown(struct net_device *ndev)
+{
+ /* not implemented*/
+ return;
+}
+
+static int umal_suspend(struct platform_device *pldev, pm_message_t state)
+{
+ struct net_device *ndev = platform_get_drvdata(pldev);
+
+ if (netif_running(ndev)) {
+ netif_device_detach(ndev);
+ umal_shutdown(ndev);
+ }
+ return 0;
+}
+
+static int umal_resume(struct platform_device *pldev)
+{
+ struct net_device *dev = platform_get_drvdata(pldev);
+
+ if (netif_running(dev)) {
+ umal_reset(dev);
+ netif_device_attach(dev);
+ }
+ return 0;
+}
+#else
+static int umal_suspend(struct platform_device *pldev, pm_message_t state) { }
+static int umal_resume(struct platform_device *pldev) { }
+#endif
+static struct platform_driver umal_driver = {
+ .probe = umal_probe,
+ .remove = __exit_p(umal_remove),
+ .driver = {
+ .name = umal_string,
+ .owner = THIS_MODULE,
+ },
+ .suspend = umal_suspend,
+ .resume = umal_resume,
+};
+
+static int __init umal_init_module(void)
+{
+ return platform_driver_register(&umal_driver);
+}
+
+static void __exit umal_cleanup_module(void)
+{
+ platform_driver_unregister(&umal_driver);
+}
+
+module_init(umal_init_module);
+module_exit(umal_cleanup_module);
> -----Original Message-----
> From: linux-arch-owner@vger.kernel.org [mailto:linux-arch-owner@vger.kernel.org] On Behalf Of Guan Xuetao
> Sent: Thursday, January 06, 2011 3:57 PM
> To: linux-arch@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [PATCHv1 0/8] unicore32 machine related files: summary
>
> From: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
>
> The whole patch could be fetched from:
> git://git.kernel.org/pub/scm/linux/kernel/git/epip/unicore32.git
> with branch name: unicore32.
> And it is divided into three patch sets: core architecture files,
> additional architecture files, and machine related files.
>
> This patch set adds the machine related files for UniCore32 ISA and PKUnity SoC.
>
> Patch 1 adds machine related core files, also including build infrastructure.
>
> Patch 2 add all hardware registers definitions, which are not split and inserted into
> different drivers.
>
> Patch 3 implements arch-specific pci bus driver.
>
> Patch 4 implements arch-specific ps2 dirver.
>
> Patch 5 implements frame buffer driver.
>
> Patch 6 implements ac97 driver.
>
> Patch 7 implements arch-specific i2c bus driver.
>
> Patch 8 implements network driver.
>
> Signed-off-by: Guan Xuetao <guanxuetao@mprc.pku.edu.cn>
> ---
> arch/unicore32/include/asm/mach/PKUnity.h | 104 ++
> arch/unicore32/include/asm/mach/bitfield.h | 24 +
> arch/unicore32/include/asm/mach/hardware.h | 45 +
> arch/unicore32/include/asm/mach/regs-ac97.h | 32 +
> arch/unicore32/include/asm/mach/regs-dmac.h | 81 +
> arch/unicore32/include/asm/mach/regs-gpio.h | 70 +
> arch/unicore32/include/asm/mach/regs-i2c.h | 63 +
> arch/unicore32/include/asm/mach/regs-intc.h | 28 +
> arch/unicore32/include/asm/mach/regs-nand.h | 79 +
> arch/unicore32/include/asm/mach/regs-ost.h | 92 ++
> arch/unicore32/include/asm/mach/regs-pci.h | 94 ++
> arch/unicore32/include/asm/mach/regs-pm.h | 126 ++
> arch/unicore32/include/asm/mach/regs-ps2.h | 20 +
> arch/unicore32/include/asm/mach/regs-resetc.h | 34 +
> arch/unicore32/include/asm/mach/regs-rtc.h | 37 +
> arch/unicore32/include/asm/mach/regs-sdc.h | 156 ++
> arch/unicore32/include/asm/mach/regs-spi.h | 98 ++
> arch/unicore32/include/asm/mach/regs-uart.h | 3 +
> arch/unicore32/include/asm/mach/regs-umal.h | 229 +++
> arch/unicore32/include/asm/mach/regs-unigfx.h | 200 +++
> arch/unicore32/include/asm/pci.h | 46 +
> arch/unicore32/kernel/pci.c | 404 +++++
> arch/unicore32/kernel/puv3-core.c | 266 ++++
> arch/unicore32/kernel/puv3-nb0916.c | 183 +++
> arch/unicore32/kernel/puv3-smw0919.c | 120 ++
> drivers/input/keyboard/Kconfig | 11 +
> drivers/input/keyboard/atkbd.c | 4 +
> drivers/input/mouse/psmouse-base.c | 41 +
> drivers/input/serio/i8042.h | 2 +
> drivers/pci/Makefile | 1 +
> drivers/staging/puv3/Kconfig | 142 ++
> drivers/staging/puv3/Makefile | 27 +
> drivers/staging/puv3/TODO | 7 +
> drivers/staging/puv3/i8042-ucio.h | 96 ++
> drivers/staging/puv3/nb0916-atkbd.h | 43 +
> drivers/staging/puv3/puv3_ac97.c | 383 +++++
> drivers/staging/puv3/puv3_i2c.c | 325 ++++
> drivers/staging/puv3/puv3_pcm.c | 449 ++++++
> drivers/staging/puv3/puv3_pcm.h | 33 +
> drivers/staging/puv3/puv3_umal.c | 2082 +++++++++++++++++++++++++
> drivers/staging/puv3/puv3_unifb.c | 972 ++++++++++++
> include/linux/fb.h | 2 +
> 42 files changed, 7254 insertions(+), 0 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2011-01-06 8:06 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-06 7:56 [PATCHv1 0/8] unicore32 machine related files: summary Guan Xuetao
2011-01-06 8:00 ` Guan Xuetao
2011-01-06 8:02 ` Guan Xuetao
2011-01-06 8:03 ` Guan Xuetao
2011-01-06 8:04 ` Guan Xuetao
2011-01-06 8:04 ` Guan Xuetao
2011-01-06 8:05 ` Guan Xuetao
2011-01-06 8:05 ` Guan Xuetao
2011-01-06 8:06 ` Guan Xuetao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®