--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -25,6 +25,8 @@
 #include <linux/usb/musb.h>
 #include <sound/tlv320aic3x.h>
 #include <linux/spi/tsc2005.h>
+#include <linux/input.h>
+#include <linux/i2c/lm8323.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -37,6 +39,7 @@
 #include <plat/onenand.h>
 #include <plat/mmc.h>
 #include <plat/serial.h>
+#include <plat/gpio-switch.h>
 
 #include "mux.h"
 
@@ -104,6 +107,152 @@ extern struct mipid_platform_data n8x0_m
 extern void n8x0_mipid_init(void);
 extern void n8x0_blizzard_init(void);
 
+/* We map the FN key as LALT to workaround an X keycode problem.
+ * The XKB map needs to be adjusted to support this. */
+#define MAP_FN_AS_LEFTALT
+
+static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
+	[0x01] = KEY_Q,
+	[0x02] = KEY_K,
+	[0x03] = KEY_O,
+	[0x04] = KEY_P,
+	[0x05] = KEY_BACKSPACE,
+	[0x06] = KEY_A,
+	[0x07] = KEY_S,
+	[0x08] = KEY_D,
+	[0x09] = KEY_F,
+	[0x0a] = KEY_G,
+	[0x0b] = KEY_H,
+	[0x0c] = KEY_J,
+
+	[0x11] = KEY_W,
+	[0x12] = KEY_F4,
+	[0x13] = KEY_L,
+	[0x14] = KEY_APOSTROPHE,
+	[0x16] = KEY_Z,
+	[0x17] = KEY_X,
+	[0x18] = KEY_C,
+	[0x19] = KEY_V,
+	[0x1a] = KEY_B,
+	[0x1b] = KEY_N,
+	[0x1c] = KEY_LEFTSHIFT, /* Actually, this is both shift keys */
+	[0x1f] = KEY_F7,
+
+	[0x21] = KEY_E,
+	[0x22] = KEY_SEMICOLON,
+	[0x23] = KEY_MINUS,
+	[0x24] = KEY_EQUAL,
+#ifdef MAP_FN_AS_LEFTALT
+	[0x2b] = KEY_LEFTALT,
+#else
+	[0x2b] = KEY_FN,
+#endif
+	[0x2c] = KEY_M,
+	[0x2f] = KEY_F8,
+
+	[0x31] = KEY_R,
+	[0x32] = KEY_RIGHTCTRL,
+	[0x34] = KEY_SPACE,
+	[0x35] = KEY_COMMA,
+	[0x37] = KEY_UP,
+	[0x3c] = KEY_COMPOSE,
+	[0x3f] = KEY_F6,
+
+	[0x41] = KEY_T,
+	[0x44] = KEY_DOT,
+	[0x46] = KEY_RIGHT,
+	[0x4f] = KEY_F5,
+	[0x51] = KEY_Y,
+	[0x53] = KEY_DOWN,
+	[0x55] = KEY_ENTER,
+	[0x5f] = KEY_ESC,
+
+	[0x61] = KEY_U,
+	[0x64] = KEY_LEFT,
+
+	[0x71] = KEY_I,
+	[0x75] = KEY_KPENTER,
+};
+
+static struct lm8323_platform_data lm8323_pdata = {
+	.repeat		= 0, /* Repeat is handled in userspace for now. */
+	.keymap		= rx44_keymap,
+	.size_x		= 8,
+	.size_y		= 12,
+	.debounce_time	= 12,
+	.active_time	= 500,
+
+	.name		= "Internal keyboard",
+	.pwm_names[0] 	= "n810::keyboard",
+	.pwm_names[1] 	= "n810::cover",
+};
+
+#define OMAP_TAG_NOKIA_BT	0x4e01
+
+struct omap_bluetooth_config {
+	u8    chip_type;
+	u8    bt_wakeup_gpio;
+	u8    host_wakeup_gpio;
+	u8    reset_gpio;
+	u8    bt_uart;
+	u8    bd_addr[6];
+	u8    bt_sysclk;
+};
+
+static struct platform_device n8x0_bt_device = {
+	.name           = "hci_h4p",
+	.id             = -1,
+	.num_resources  = 0,
+};
+
+void __init n8x0_bt_init(void)
+{
+	const struct omap_bluetooth_config *bt_config;
+
+	bt_config = (void *) omap_get_config(OMAP_TAG_NOKIA_BT,
+					     struct omap_bluetooth_config);
+	n8x0_bt_device.dev.platform_data = (void *) bt_config;
+	if (platform_device_register(&n8x0_bt_device) < 0)
+		BUG();
+}
+
+static struct omap_gpio_switch n8x0_gpio_switches[] __initdata = {
+	{
+		.name			= "headphone",
+		.gpio			= -1,
+		.debounce_rising	= 200,
+		.debounce_falling	= 200,
+	}, {
+		.name			= "cam_act",
+		.gpio			= -1,
+		.debounce_rising	= 200,
+		.debounce_falling	= 200,
+	}, {
+		.name			= "cam_turn",
+		.gpio			= -1,
+		.debounce_rising	= 100,
+		.debounce_falling	= 100,
+	}, {
+		.name			= "slide",
+		.gpio			= -1,
+		.debounce_rising	= 200,
+		.debounce_falling	= 200,
+	}, {
+		.name			= "kb_lock",
+		.gpio			= -1,
+		.debounce_rising	= 200,
+		.debounce_falling	= 200,
+	},
+};
+
+static void __init n8x0_gpio_switches_init(void)
+{
+	/* The switches are actually registered through ATAG mechanism.
+	 * This just updates the parameters (thus .gpio is -1) */
+	omap_register_gpio_switches(n8x0_gpio_switches,
+				    ARRAY_SIZE(n8x0_gpio_switches));
+}
+
 #define TUSB6010_ASYNC_CS	1
 #define TUSB6010_SYNC_CS	4
 #define TUSB6010_GPIO_INT	58
@@ -799,6 +948,11 @@ static struct aic3x_pdata n810_aic33_dat
 };
 
 static struct i2c_board_info n810_i2c_board_info_2[] __initdata = {
+ 	{
+		I2C_BOARD_INFO("lm8323", 0x45),
+		.irq		= OMAP_GPIO_IRQ(109),
+		.platform_data	= &lm8323_pdata,
+	},
 	{
 		I2C_BOARD_INFO("tlv320aic3x", 0x18),
 		.platform_data = &n810_aic33_data,
@@ -856,7 +1010,9 @@ static inline void board_serial_init(voi
 static void __init n8x0_init_machine(void)
 {
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
+	n8x0_gpio_switches_init();
 	n8x0_cbus_init();
+	n8x0_bt_init();
 
 	/* FIXME: add n810 spi devices */
 	tsc2005_set_config();
