Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa7499ef authored by GuanXuetao's avatar GuanXuetao
Browse files

unicore32 machine related files: core files



This patch adds machine related core files, also including build infrastructure.

Signed-off-by: default avatarGuan Xuetao <gxt@mprc.pku.edu.cn>
Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
parent 70fac51f
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -231,6 +231,31 @@ config PUV3_RTC
	tristate "PKUnity v3 RTC Support"
	depends on !ARCH_FPGA

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

endmenu

endif

endif

source "drivers/Kconfig"
+270 −0
Original line number Diff line number Diff line
/*
 *  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.
 */

#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 <linux/cnt32_to_63.h>
#include <linux/usb/musb.h>

#include <asm/irq.h>
#include <mach/hardware.h>
#include <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 puv3_ps2_init(void)
{
	struct clk *bclk32;

	bclk32 = clk_get(NULL, "BUS32_CLK");
	PS2_CNT = clk_get_rate(bclk32) / 200000; /* should > 5us */
}

void __init puv3_core_init(void)
{
	puv3_init_pm();
	puv3_ps2_init();

	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));
}
+145 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#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 <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 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_pwm_backlight_data nb0916_backlight_data = {
	.pwm_id		= 0,
	.max_brightness	= 100,
	.dft_brightness	= 100,
	.pwm_period_ns	= 70 * 1024,
};

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 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_device_register_simple("PKUnity-v3-I2C", -1,
			puv3_i2c_resources, ARRAY_SIZE(puv3_i2c_resources));

	platform_device_register_data(&platform_bus, "pwm-backlight", -1,
			&nb0916_backlight_data, sizeof(nb0916_backlight_data));

	platform_device_register_data(&platform_bus, "gpio-keys", -1,
			&nb0916_gpio_button_data, sizeof(nb0916_gpio_button_data));

	platform_device_register_resndata(&platform_bus, "physmap-flash", -1,
			&physmap_flash_resource, 1,
			&physmap_flash_data, sizeof(physmap_flash_data));

	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);