Add MPIO HD200 port - new files


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25725 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/keymaps/keymap-mpio-hd200.c b/apps/keymaps/keymap-mpio-hd200.c
new file mode 100644
index 0000000..95dec41
--- /dev/null
+++ b/apps/keymaps/keymap-mpio-hd200.c
@@ -0,0 +1,172 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include "action.h"
+#include "button.h"
+#include "settings.h"
+
+/*
+ * The format of the list is as follows
+ * { Action Code,   Button code,    Prereq button code }
+ * if there's no need to check the previous button's value, use BUTTON_NONE
+ * Insert LAST_ITEM_IN_LIST at the end of each mapping
+ */
+
+/* CONTEXT_CUSTOM's used in this file...
+
+CONTEXT_CUSTOM|CONTEXT_TREE = the standard list/tree defines (without directions)
+
+
+*/
+
+static const struct button_mapping button_context_standard[]  = {
+    { ACTION_STD_PREV,          BUTTON_PREV,                 BUTTON_NONE },
+    { ACTION_STD_PREVREPEAT,    BUTTON_PREV|BUTTON_REPEAT,   BUTTON_NONE },
+    { ACTION_STD_NEXT,          BUTTON_NEXT,                 BUTTON_NONE },
+    { ACTION_STD_NEXTREPEAT,    BUTTON_NEXT|BUTTON_REPEAT,   BUTTON_NONE },
+    { ACTION_STD_CANCEL,        BUTTON_REC|BUTTON_REL,       BUTTON_REC },
+    { ACTION_STD_OK,            BUTTON_SELECT|BUTTON_REL,    BUTTON_SELECT },
+    { ACTION_STD_MENU,          BUTTON_REC|BUTTON_REPEAT,    BUTTON_REC },
+    { ACTION_STD_QUICKSCREEN,   BUTTON_PLAY|BUTTON_REPEAT,   BUTTON_PLAY },
+    { ACTION_STD_CONTEXT,       BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT },
+
+    LAST_ITEM_IN_LIST
+}; /* button_context_standard */
+
+static const struct button_mapping button_context_tree[]  = {
+    { ACTION_TREE_WPS,          BUTTON_PLAY|BUTTON_REL,      BUTTON_PLAY },
+    { ACTION_TREE_STOP,         BUTTON_PLAY|BUTTON_REPEAT,   BUTTON_PLAY },
+
+    LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_tree */
+
+static const struct button_mapping button_context_tree_scroll_lr[]  = {
+    { ACTION_NONE,              BUTTON_PREV,                BUTTON_NONE },
+    { ACTION_STD_CANCEL,        BUTTON_PREV|BUTTON_REL,     BUTTON_PREV },
+    { ACTION_TREE_ROOT_INIT,    BUTTON_PREV|BUTTON_REPEAT,  BUTTON_PREV },
+    { ACTION_TREE_PGLEFT,       BUTTON_PREV|BUTTON_REPEAT,  BUTTON_NONE },
+    { ACTION_TREE_PGLEFT,       BUTTON_PREV|BUTTON_REL,     BUTTON_PREV|BUTTON_REPEAT },
+    { ACTION_NONE,              BUTTON_NEXT,               BUTTON_NONE },
+    { ACTION_STD_OK,            BUTTON_NEXT|BUTTON_REL,    BUTTON_NEXT },
+    { ACTION_TREE_PGRIGHT,      BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
+    { ACTION_TREE_PGRIGHT,      BUTTON_NEXT|BUTTON_REL,    BUTTON_NEXT|BUTTON_REPEAT },    
+    LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE),
+}; /* button_context_tree_scroll_lr */
+
+static const struct button_mapping button_context_wps[]  = {
+    { ACTION_WPS_PLAY,      BUTTON_PLAY|BUTTON_REL,         BUTTON_PLAY },
+    { ACTION_WPS_STOP,      BUTTON_PLAY|BUTTON_REPEAT,      BUTTON_PLAY },
+    { ACTION_WPS_SKIPPREV,  BUTTON_PREV|BUTTON_REL,         BUTTON_PREV },
+    { ACTION_WPS_SEEKBACK,  BUTTON_PREV|BUTTON_REPEAT,      BUTTON_NONE },
+    { ACTION_WPS_STOPSEEK,  BUTTON_PREV|BUTTON_REL,         BUTTON_PREV|BUTTON_REPEAT },
+    { ACTION_WPS_SKIPNEXT,  BUTTON_NEXT|BUTTON_REL,        BUTTON_NEXT },
+    { ACTION_WPS_SEEKFWD,   BUTTON_NEXT|BUTTON_REPEAT,     BUTTON_NONE },
+    { ACTION_WPS_STOPSEEK,  BUTTON_NEXT|BUTTON_REL,        BUTTON_NEXT|BUTTON_REPEAT },
+    { ACTION_WPS_VOLDOWN,   BUTTON_VOL_DOWN,                 BUTTON_NONE },
+    { ACTION_WPS_VOLDOWN,   BUTTON_VOL_DOWN|BUTTON_REPEAT,   BUTTON_NONE },
+    { ACTION_WPS_VOLUP,     BUTTON_VOL_UP,                  BUTTON_NONE },
+    { ACTION_WPS_VOLUP,     BUTTON_VOL_UP|BUTTON_REPEAT,    BUTTON_NONE },
+    { ACTION_WPS_BROWSE,    BUTTON_SELECT|BUTTON_REL,           BUTTON_SELECT },
+    { ACTION_WPS_CONTEXT,   BUTTON_SELECT|BUTTON_REPEAT,        BUTTON_SELECT },
+    { ACTION_WPS_MENU,          BUTTON_REC|BUTTON_REL,         BUTTON_REC },
+    { ACTION_WPS_QUICKSCREEN,   BUTTON_SELECT|BUTTON_REPEAT,      BUTTON_SELECT },
+
+    LAST_ITEM_IN_LIST,
+}; /* button_context_wps */
+
+static const struct button_mapping button_context_settings[]  = {
+    { ACTION_SETTINGS_INC,          BUTTON_VOL_UP,         BUTTON_NONE },
+    { ACTION_SETTINGS_INCREPEAT,    BUTTON_VOL_UP|BUTTON_REPEAT,  BUTTON_NONE },
+    { ACTION_SETTINGS_DEC,          BUTTON_VOL_DOWN,          BUTTON_NONE },
+    { ACTION_SETTINGS_DECREPEAT,    BUTTON_VOL_DOWN|BUTTON_REPEAT,  BUTTON_NONE },
+    { ACTION_STD_PREV,              BUTTON_PREV,                  BUTTON_NONE },
+    { ACTION_STD_PREVREPEAT,        BUTTON_PREV|BUTTON_REPEAT,    BUTTON_NONE },
+    { ACTION_STD_NEXT,              BUTTON_NEXT,                BUTTON_NONE },
+    { ACTION_STD_NEXTREPEAT,        BUTTON_NEXT|BUTTON_REPEAT,  BUTTON_NONE },
+    { ACTION_STD_OK,                BUTTON_SELECT|BUTTON_REL,    BUTTON_NONE },
+    { ACTION_STD_CANCEL,            BUTTON_REC|BUTTON_REL,      BUTTON_REC },
+
+    LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_settings */
+
+static const struct button_mapping button_context_yesno[]  = {
+    { ACTION_YESNO_ACCEPT,          BUTTON_SELECT,                  BUTTON_NONE },
+    LAST_ITEM_IN_LIST
+}; /* button_context_yesno */
+
+static const struct button_mapping button_context_bmark[]  = {
+    { ACTION_BMS_DELETE,          BUTTON_SELECT|BUTTON_REPEAT,       BUTTON_SELECT },
+    LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST),
+}; /* button_context_bmark */
+
+static const struct button_mapping button_context_quickscreen[]  = {
+    { ACTION_QS_TOP,        BUTTON_SELECT,                    BUTTON_NONE },
+    { ACTION_QS_TOP,        BUTTON_SELECT|BUTTON_REPEAT,      BUTTON_NONE },
+    { ACTION_QS_DOWN,       BUTTON_PLAY,                    BUTTON_NONE },
+    { ACTION_QS_DOWN,       BUTTON_PLAY|BUTTON_REPEAT,      BUTTON_NONE },
+    { ACTION_QS_LEFT,       BUTTON_PREV,                    BUTTON_NONE },
+    { ACTION_QS_LEFT,       BUTTON_PREV|BUTTON_REPEAT,      BUTTON_NONE },
+    { ACTION_QS_RIGHT,      BUTTON_NEXT,                   BUTTON_NONE },
+    { ACTION_QS_RIGHT,      BUTTON_NEXT|BUTTON_REPEAT,     BUTTON_NONE },
+    { ACTION_STD_CANCEL,    BUTTON_REC,                  BUTTON_NONE },
+
+    LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_quickscreen */
+
+static const struct button_mapping button_context_pitchscreen[]  = {
+    { ACTION_PS_INC_SMALL,      BUTTON_VOL_UP,                BUTTON_NONE },
+    { ACTION_PS_INC_BIG,        BUTTON_VOL_UP|BUTTON_REPEAT,  BUTTON_NONE },
+    { ACTION_PS_DEC_SMALL,      BUTTON_VOL_DOWN,                BUTTON_NONE },
+    { ACTION_PS_DEC_BIG,        BUTTON_VOL_DOWN|BUTTON_REPEAT,  BUTTON_NONE },
+    { ACTION_PS_NUDGE_LEFT,     BUTTON_PREV,                BUTTON_NONE },
+    { ACTION_PS_NUDGE_LEFTOFF,  BUTTON_PREV|BUTTON_REL,     BUTTON_NONE },
+    { ACTION_PS_NUDGE_RIGHT,    BUTTON_NEXT,               BUTTON_NONE },
+    { ACTION_PS_NUDGE_RIGHTOFF, BUTTON_NEXT|BUTTON_REL,    BUTTON_NONE },
+    { ACTION_PS_TOGGLE_MODE,    BUTTON_PLAY,                BUTTON_NONE },
+    { ACTION_PS_RESET,          BUTTON_SELECT,                BUTTON_NONE },
+    { ACTION_PS_EXIT,           BUTTON_REC,              BUTTON_NONE },
+    { ACTION_PS_SLOWER,         BUTTON_PREV|BUTTON_REPEAT,  BUTTON_NONE },
+    { ACTION_PS_FASTER,         BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
+
+    LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_pitchscreen */
+
+const struct button_mapping* get_context_mapping(int context)
+{
+    switch (context)
+    {
+        case CONTEXT_STD:
+            return button_context_standard;
+        case CONTEXT_WPS:
+            return button_context_wps;
+
+        case CONTEXT_TREE:
+        case CONTEXT_LIST:
+        case CONTEXT_MAINMENU:
+
+        case CONTEXT_SETTINGS:
+        case CONTEXT_SETTINGS|CONTEXT_REMOTE:
+        default:
+            return button_context_standard;
+    }
+    return button_context_standard;
+}
+
diff --git a/bootloader/mpio_hd200.c b/bootloader/mpio_hd200.c
new file mode 100644
index 0000000..68152f3
--- /dev/null
+++ b/bootloader/mpio_hd200.c
@@ -0,0 +1,459 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "inttypes.h"
+#include "string.h"
+#include "cpu.h"
+#include "system.h"
+#include "lcd.h"
+#include "kernel.h"
+#include "thread.h"
+#include "storage.h"
+#include "usb.h"
+#include "disk.h"
+#include "font.h"
+#include "adc.h"
+#include "backlight.h"
+#include "backlight-target.h"
+#include "button.h"
+#include "panic.h"
+#include "power.h"
+#include "powermgmt.h"
+#include "file.h"
+
+#include "common.h"
+
+#include <stdarg.h>
+
+/* Maximum allowed firmware image size. 10MB is more than enough */
+#define MAX_LOADSIZE (10*1024*1024)
+
+#define DRAM_START 0x31000000
+
+#define BOOTMENU_TIMEOUT (10*HZ)
+#define BOOTMENU_OPTIONS 3
+
+/* From common.c */
+extern int line;
+static const char *bootmenu_options[] = {
+    "Boot rockbox",
+    "Boot MPIO firmware",
+    "Shutdown"
+};
+
+enum option_t {
+    rockbox,
+    mpio_firmware,
+    shutdown
+};
+
+int usb_screen(void)
+{
+   return 0;
+}
+
+char version[] = APPSVERSION;
+
+bool _charger_inserted(void)
+{
+    return (GPIO1_READ & (1<<14)) ? false : true;
+}
+
+bool _battery_full(void)
+{
+    return (GPIO_READ & (1<<30)) ? true : false;
+}
+
+/* Reset the cookie for the crt0 crash check */
+inline void __reset_cookie(void)
+{
+    asm(" move.l #0,%d0");
+    asm(" move.l %d0,0x10017ffc");
+}
+
+void start_rockbox(void)
+{
+    adc_close();
+    asm(" move.w #0x2700,%sr");
+    __reset_cookie();
+    asm(" move.l %0,%%d0" :: "i"(DRAM_START));
+    asm(" movec.l %d0,%vbr");
+    asm(" move.l %0,%%sp" :: "m"(*(int *)DRAM_START));
+    asm(" move.l %0,%%a0" :: "m"(*(int *)(DRAM_START+4)));
+    asm(" jmp (%a0)");
+}
+
+void start_mpio_firmware(void)
+{
+    asm(" move.w #0x2700,%sr");
+    __reset_cookie();
+    asm(" movec.l %d0,%vbr");
+    asm(" move.l 0,%sp");
+    asm(" jmp 8");
+}
+
+void __reset(void)
+{
+    asm(" move.w #0x2700,%sr");
+    __reset_cookie();
+    asm(" movec.l %d0,%vbr");
+    asm(" move.l (0), %sp");
+    asm(" movea.l (4),%a0");
+    asm(" jmp (%a0)");
+}
+
+void __shutdown(void)
+{
+    /* We need to gracefully spin down the disk to prevent clicks. */
+    if (ide_powered())
+    {
+        /* Make sure ATA has been initialized. */
+        storage_init();
+        
+        /* And put the disk into sleep immediately. */
+        storage_sleepnow();
+    }
+
+    /* Backlight OFF */
+    _backlight_off();
+    __reset_cookie();
+
+    if (_charger_inserted())
+    {
+        /* reset instead of power_off() */
+        __reset();
+    }
+    else
+    {
+        power_off();
+    }
+}
+
+/* Print the battery voltage (and a warning message). */
+void check_battery(void)
+{
+
+    int battery_voltage, batt_int, batt_frac;
+    
+    battery_voltage = battery_adc_voltage();
+    batt_int = battery_voltage / 1000;
+    batt_frac = (battery_voltage % 1000) / 10;
+
+    printf("Battery: %d.%02dV", batt_int, batt_frac);
+
+    if (battery_voltage <= 3500) 
+    {
+        printf("WARNING! BATTERY LOW!!");
+        sleep(HZ*2);
+    }
+
+}
+
+
+void lcd_putstring_centered(const char *string)
+{
+    int w,h;
+    font_getstringsize(string, &w, &h, FONT_SYSFIXED);
+    lcd_putsxy((LCD_WIDTH-w)/2, (LCD_HEIGHT-h)/2, string);
+}
+
+void bootmenu(void)
+{
+    int rc;
+    enum option_t i;
+    enum option_t option = rockbox;
+    int button;
+    const char select[] = "->";
+    long start_tick = current_tick;
+
+    /* backbone of menu */
+    /* run the loader */
+    printf("Rockbox boot loader");
+    printf("Ver: %s", version);
+
+    check_battery();
+
+    printf("");
+    printf("=========================");
+
+    line += BOOTMENU_OPTIONS+2; /* skip lines */
+
+    printf("=========================");
+    printf("");
+    printf(" [FF] [PREV] to move ");
+    printf(" [PLAY] to confirm ");
+
+    /* content of menu and keys handling */
+    while (TIME_BEFORE(current_tick,start_tick + BOOTMENU_TIMEOUT))
+    {
+        /* Draw the menu. */
+        line = 6; /* move below header */
+
+        for (i=0;i<BOOTMENU_OPTIONS;i++)
+        {
+            if (i != option)
+                printf("   %s",bootmenu_options[i]);
+            else
+                printf("%s %s",select,bootmenu_options[i]);
+        }
+
+        line = 15;
+
+        printf("Time left: %ds",(BOOTMENU_TIMEOUT - 
+                                 (current_tick - start_tick))/HZ);
+
+        lcd_update();
+
+        button = button_get_w_tmo(HZ);
+
+        switch (button)
+        {
+            case BUTTON_PREV:
+                if (option > rockbox)
+                    option--;
+                else
+                    option = shutdown;
+                break;
+
+            case BUTTON_NEXT:
+                if (option < shutdown)
+                    option++;
+                else
+                    option = rockbox;
+                break;
+
+            case BUTTON_PLAY:
+            case (BUTTON_PLAY|BUTTON_REC):
+                reset_screen();
+
+                switch (option)
+                {
+                    case rockbox:
+                        rc = storage_init();
+                        if(rc)
+                        {
+                            printf("ATA error: %d", rc);
+                            sleep(HZ*5);
+                            __shutdown();
+                        }
+
+                        disk_init();
+
+                        rc = disk_mount_all();
+                        if (rc<=0)
+                        {
+                            printf("No partition found");
+                            sleep(HZ*5);
+                            __shutdown();
+                        }
+
+                        printf("Loading firmware");
+                        rc = load_firmware((unsigned char *)DRAM_START, 
+                                           BOOTFILE, MAX_LOADSIZE);
+                        printf("Result: %s", strerror(rc));
+
+                        if (rc < EOK)
+                        {
+                            printf("Error!");
+                            printf("Can't load " BOOTFILE ": ");
+                            printf(strerror(rc));
+                            sleep(HZ*5);
+                            __shutdown();
+                        }
+                        else
+                        {
+                            start_rockbox();
+                        }
+
+                        break;
+
+                    case mpio_firmware:
+                        start_mpio_firmware();
+                        break;
+
+                    default:
+                        __shutdown();
+                        break;
+                }
+        }
+}
+/* timeout */
+__shutdown();
+}
+
+void main(void)
+{
+    /* messages */
+    const char usb_connect_msg[] = "Bootloader USB mode";
+    const char charging_msg[] = "Charging...";
+    const char complete_msg[] = "Charging complete";
+    const char hold_msg[] = "Hold switch on";
+    const char shutdown_msg[] = "Shutting down...";
+
+    /* helper variables for messages */
+    bool blink_toggle = false;
+    const char *msg;
+
+    bool on_button = false;
+    int button;
+
+    /* We want to read the buttons as early as possible, before the user
+       releases the ON button */
+
+    or_l( ((1<<24)|(1<<4)), &GPIO1_FUNCTION); /* main Hold & Play */
+    and_l( ~((1<<24)|(1<<4)), &GPIO1_ENABLE); /* HiZ */
+    
+    if (GPIO1_READ & (1<<24))
+        on_button = true;
+
+    power_init();
+
+    system_init();
+    kernel_init();
+
+    set_cpu_frequency(CPUFREQ_NORMAL);
+    coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
+
+    enable_irq();
+    lcd_init();
+
+    backlight_init();
+    font_init();
+    lcd_setfont(FONT_SYSFIXED);
+
+    adc_init();
+    button_init();
+    usb_init();
+
+    /* handle charging */
+    if( _charger_inserted())
+    {
+        or_l((1<<15),&GPIO_OUT);
+
+        cpu_idle_mode(true);
+
+        while( _charger_inserted() && 
+               usb_detect() != USB_INSERTED &&
+               !on_button)
+        {
+            button = button_get_w_tmo(HZ);
+
+            switch(button)
+            {
+            case BUTTON_ON:
+                on_button = true;
+                reset_screen();
+                break;
+
+            case BUTTON_NONE: /* Timeout */
+
+                if(!_battery_full())
+                {
+                    /* To be replaced with a nice animation */
+                    blink_toggle = !blink_toggle;
+                    msg = charging_msg;
+                }
+                else
+                {
+                    blink_toggle = true;
+                    msg = complete_msg;
+                }
+
+                reset_screen();
+                if(blink_toggle)
+                    lcd_putstring_centered(msg);
+
+                check_battery();
+                break;
+            }
+
+        }
+        cpu_idle_mode(false);
+    }
+
+    /* handle USB in bootloader */
+    if (usb_detect() == USB_INSERTED)
+    {
+        ide_power_enable(true);
+        sleep(HZ/20);
+        usb_enable(true);
+        cpu_idle_mode(true);
+
+        while (usb_detect() == USB_INSERTED)
+        {
+            line = 0;
+
+            reset_screen();
+
+            if(blink_toggle)
+            {
+                 lcd_putstring_centered(usb_connect_msg);
+            }
+
+            check_battery();
+            blink_toggle = !blink_toggle;
+
+            storage_spin(); /* Prevent the drive from spinning down */
+            sleep(HZ);
+        }
+
+        cpu_idle_mode(false);
+        usb_enable(false);
+
+        sleep(HZ);
+        reset_screen();
+        lcd_update();
+    }
+
+    /* handle ON button press */
+    if (on_button)
+    {
+        if (button_hold() &&
+            !_charger_inserted() &&
+            usb_detect() != USB_INSERTED)
+        {
+            lcd_putstring_centered(hold_msg);
+            lcd_update();
+            sleep(HZ*3);
+            __shutdown();
+        }
+        
+    }
+    else
+    {
+        lcd_putstring_centered(shutdown_msg);
+        lcd_update();
+        sleep(HZ*3);
+        __shutdown();
+    }
+
+    
+    bootmenu();
+}
+
+/* These functions are present in the firmware library, but we reimplement
+   them here because the originals do a lot more than we want */
+void screen_dump(void)
+{
+}
diff --git a/firmware/export/config/mpiohd200.h b/firmware/export/config/mpiohd200.h
new file mode 100644
index 0000000..369f443
--- /dev/null
+++ b/firmware/export/config/mpiohd200.h
@@ -0,0 +1,191 @@
+/*
+ * This config file is for MPIO HD200
+ */
+#define TARGET_TREE /* this target is using the target tree system */
+
+/* For Rolo and boot loader */
+#define MODEL_NUMBER 69
+
+#define MODEL_NAME   "MPIO HD200"
+
+/* define this if you use an ATA controller */
+#define CONFIG_STORAGE STORAGE_ATA
+#define HAVE_LBA48
+
+/* define this if you have recording possibility */
+/* not implemented yet 
+ * #define HAVE_RECORDING
+ */
+
+
+/* Define bitmask of input sources - recordable bitmask can be defined
+ *  explicitly if different
+ * not implemented yet
+ */
+
+#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO)
+
+
+/* define the bitmask of hardware sample rates */
+#define HW_SAMPR_CAPS   (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
+
+/* define the bitmask of recording sample rates
+ * not implemented yet
+ *#define REC_SAMPR_CAPS  (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
+ */
+
+/* define this if you have a bitmap LCD display */
+#define HAVE_LCD_BITMAP
+
+/* define this if you want album art for this target */
+#define HAVE_ALBUMART
+
+/* define this to enable bitmap scaling */
+#define HAVE_BMP_SCALING
+
+/* define this to enable JPEG decoding */
+#define HAVE_JPEG
+
+/* define this if you can flip your LCD */
+#define HAVE_LCD_FLIP
+
+/* define this if you can invert the colours on your LCD */
+#define HAVE_LCD_INVERT
+
+/* define this if you have access to the quickscreen */
+#define HAVE_QUICKSCREEN
+
+/* define this if you have access to the pitchscreen */
+#define HAVE_PITCHSCREEN
+
+/* define this if you would like tagcache to build on this target */
+#define HAVE_TAGCACHE
+
+/* LCD dimensions */
+#define LCD_WIDTH  128
+#define LCD_HEIGHT 128
+#define LCD_DEPTH  2
+
+#define LCD_PIXELFORMAT VERTICAL_INTERLEAVED
+
+/* Display colours, for screenshots and sim (0xRRGGBB) */
+#define LCD_DARKCOLOR       0x000000
+#define LCD_BRIGHTCOLOR     0x5a915a
+#define LCD_BL_DARKCOLOR    0x000000
+#define LCD_BL_BRIGHTCOLOR  0x82b4fa
+
+#define CONFIG_KEYPAD MPIO_HD200_PAD
+
+#define AB_REPEAT_ENABLE 1
+#define ACTION_WPSAB_SINGLE ACTION_WPS_BROWSE
+
+/* Define this if you do software codec */
+#define CONFIG_CODEC SWCODEC
+
+#define CONFIG_LCD LCD_TL0350A
+#define HAVE_LCD_SHUTDOWN
+
+/* Define this for LCD backlight available */
+#define HAVE_BACKLIGHT
+#define HAVE_BACKLIGHT_BRIGHTNESS
+#define MIN_BRIGHTNESS_SETTING      0 
+#define MAX_BRIGHTNESS_SETTING      31
+#define DEFAULT_BRIGHTNESS_SETTING  20
+
+
+/* define this if you have a disk storage, i.e. something
+   that needs spinups and can cause skips when shaked */
+#define HAVE_DISK_STORAGE
+
+/* Define this if you have a software controlled poweroff */
+#define HAVE_SW_POWEROFF
+
+/* The number of bytes reserved for loadable codecs */
+#define CODEC_SIZE 0x100000
+
+/* The number of bytes reserved for loadable plugins */
+#define PLUGIN_BUFFER_SIZE 0x80000
+
+/* FM Tuner
+ * turn off for now
+ */
+#define CONFIG_TUNER       TEA5767
+#define CONFIG_TUNER_XTAL  32768
+
+
+/* we have WM8750 codec in I2S slave mode */
+#define HAVE_WM8750
+#define CODEC_SLAVE
+
+#define BATTERY_CAPACITY_DEFAULT 950 /* default battery capacity */
+#define BATTERY_CAPACITY_MIN    950   /* min. capacity selectable */
+#define BATTERY_CAPACITY_MAX    2250  /* max. capacity selectable */
+#define BATTERY_CAPACITY_INC    50    /* capacity increment */
+#define BATTERY_TYPES_COUNT     1     /* only one type */
+
+#define CONFIG_CHARGING CHARGING_MONITOR
+
+/* define current usage levels */
+/* additional current when remote connected */
+/*
+#define CURRENT_REMOTE      8 
+*/
+#ifndef SIMULATOR
+
+/* Define this if your LCD can set contrast */
+#define HAVE_LCD_CONTRAST
+
+/* Define this if you have a Motorola SCF5249 */
+#define CONFIG_CPU MCF5249
+
+/* Define this if you want to use coldfire's i2c interface */
+#define CONFIG_I2C I2C_COLDFIRE
+
+/* OF resets device instead of poweroff while charging
+ * this triggers bootloader code which takes care of charging.
+ * I have feeling that powering off while charging may cause
+ * partition table corruption I am experiencing from time to time
+ */
+
+/* define this if the hardware can be powered off while charging */
+/* #define HAVE_POWEROFF_WHILE_CHARGING */
+
+/* The size of the flash ROM */
+#define FLASH_SIZE 0x200000
+
+/* Define this to the CPU frequency */
+#define CPU_FREQ      11289600
+
+/* Define this if you have ATA power-off control */
+#define HAVE_ATA_POWER_OFF
+
+/* Offset ( in the firmware file's header ) to the file length */
+#define FIRMWARE_OFFSET_FILE_LENGTH 0
+
+/* Offset ( in the firmware file's header ) to the file CRC */
+#define FIRMWARE_OFFSET_FILE_CRC 0
+
+/* Offset ( in the firmware file's header ) to the real data */
+#define FIRMWARE_OFFSET_FILE_DATA 8
+
+/* Define this if you have adjustable CPU frequency */
+#define HAVE_ADJUSTABLE_CPU_FREQ
+
+#define BOOTFILE_EXT "mpio"
+#define BOOTFILE "rockbox." BOOTFILE_EXT
+#define BOOTDIR "/.rockbox"
+
+#define BOOTLOADER_ENTRYPOINT  0x001F0000
+#define FLASH_ENTRYPOINT       0x00001000
+#define FLASH_MAGIC            0xfbfbfbf1
+
+#endif /* SIMULATOR */
+
+/** Port-specific settings **/
+
+/* Main LCD contrast range and defaults  taken from OF*/
+#define MIN_CONTRAST_SETTING        24
+#define MAX_CONTRAST_SETTING        63
+#define DEFAULT_CONTRAST_SETTING    27 /* 0x1B */
+
+#define IRAM_LCDFRAMEBUFFER IBSS_ATTR /* put the lcd frame buffer in IRAM */
diff --git a/firmware/target/coldfire/mpio/app.lds b/firmware/target/coldfire/mpio/app.lds
new file mode 100644
index 0000000..d087f99
--- /dev/null
+++ b/firmware/target/coldfire/mpio/app.lds
@@ -0,0 +1,145 @@
+#include "config.h"
+
+ENTRY(start)
+
+OUTPUT_FORMAT(elf32-m68k)
+STARTUP(target/coldfire/crt0.o)
+
+#define PLUGINSIZE PLUGIN_BUFFER_SIZE
+#define CODECSIZE CODEC_SIZE
+
+#ifdef DEBUG
+#define STUBOFFSET 0x10000
+#else
+#define STUBOFFSET 0
+#endif
+
+#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGINSIZE - STUBOFFSET - CODECSIZE
+
+#define DRAMORIG 0x31000000 + STUBOFFSET
+#define IRAMORIG 0x10000000
+#define IRAMSIZE 0xc000
+
+/* End of the audio buffer, where the codec buffer starts */
+#define ENDAUDIOADDR  (DRAMORIG + DRAMSIZE)
+
+/* Where the codec buffer ends, and the plugin buffer starts */
+#define ENDADDR (ENDAUDIOADDR + CODECSIZE)
+
+MEMORY
+{
+    DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
+    IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
+}
+
+SECTIONS
+{
+    .vectors :
+    {
+        loadaddress = .;
+        _loadaddress = .;
+        KEEP(*(.resetvectors));
+        *(.resetvectors);
+        KEEP(*(.vectors));
+        *(.vectors);
+    } > DRAM
+
+    .text :
+    {
+        . = ALIGN(0x200);
+        *(.init.text)
+        *(.text*)
+        . = ALIGN(0x4);
+    } > DRAM
+
+    .rodata :
+    {
+        *(.rodata)  /* problems without this, dunno why */
+        *(.rodata*)
+        *(.rodata.str1.1)
+        *(.rodata.str1.4)
+        . = ALIGN(0x4);
+
+        /* Pseudo-allocate the copies of the data sections */
+        _datacopy = .;
+    } > DRAM
+
+    /* TRICK ALERT! For RAM execution, we put the .data section at the
+       same load address as the copy. Thus, we don't waste extra RAM
+       when we don't actually need the copy.  */
+    .data : AT ( _datacopy )
+    {
+        _datastart = .;
+        *(.data*)
+        . = ALIGN(0x4);
+        _dataend  = .;
+    } > DRAM
+
+    /DISCARD/ :
+    {
+        *(.eh_frame)
+    }
+
+    .iram IRAMORIG :
+    {
+        _iramstart = .;
+        *(.icode)
+        *(.irodata)
+        *(.idata)
+        _iramend = .;
+    } > IRAM AT> DRAM
+
+    _iramcopy = LOADADDR(.iram);
+    _noloaddram = LOADADDR(.iram);
+
+    .ibss (NOLOAD) :
+    {
+        _iedata = .;
+        *(.ibss)
+        . = ALIGN(0x4);
+        _iend = .;
+    } > IRAM
+
+    .stack (NOLOAD) :
+    {
+       *(.stack)
+       stackbegin = .;
+       . += 0x2000;
+       stackend = .;
+    } > IRAM
+
+    .bss _noloaddram (NOLOAD) :
+    {
+       _edata = .;
+        *(.bss*)
+        *(COMMON)
+        . = ALIGN(0x4);
+       _end = .;
+    } > DRAM
+
+    .audiobuf (NOLOAD) :
+    {
+    	. = ALIGN(4);
+        _audiobuffer = .;
+        audiobuffer = .;
+    } > DRAM
+
+    .audiobufend ENDAUDIOADDR (NOLOAD) :
+    {
+        audiobufend = .;
+        _audiobufend = .;
+    } > DRAM
+
+    .codec ENDAUDIOADDR (NOLOAD) :
+    {
+        codecbuf = .;
+        _codecbuf = .;
+    }
+
+    .plugin ENDADDR (NOLOAD) :
+    {
+        _pluginbuf = .;
+        pluginbuf = .;
+    }
+}
+
diff --git a/firmware/target/coldfire/mpio/ata-as-mpio.S b/firmware/target/coldfire/mpio/ata-as-mpio.S
new file mode 100644
index 0000000..4a6bd3e
--- /dev/null
+++ b/firmware/target/coldfire/mpio/ata-as-mpio.S
@@ -0,0 +1,757 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: ata-as-coldfire.S 17847 2008-06-28 18:10:04Z bagder $
+ *
+ * Copyright (C) 2006 by Jens Arnold
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+    .section    .icode,"ax",@progbits
+
+    .equ    .ata_port, 0x20000020
+    .equ    .swapmask, 0x00FF00FF
+    .align  2
+    .global copy_read_sectors
+    .type   copy_read_sectors,@function
+    
+/* Read a number of words from the ATA data port
+ *
+ * Utilises line bursts, assumes there is at least one full line to copy.
+ *
+ * Arguments:
+ *   (4,%sp) - buffer address
+ *   (8,%sp) - word count
+ *
+ * Register usage:
+ *   %a0 - current address
+ *   %a1 - end address
+ *   %a2 - ata port
+ *   %d0 - scratch
+ *   %d1 - shift count
+ *   %d2-%d6 - read buffers
+ *
+ *   %d7 - byte swap scrach register
+ *   %a3 - byte swap mask
+ */
+
+copy_read_sectors:
+    lea.l   (-32, %sp), %sp
+    movem.l %d2-%d7/%a2-%a3, (%sp)
+    movem.l (36, %sp), %a0-%a1
+    add.l   %a1, %a1
+    add.l   %a0, %a1
+    lea.l   .ata_port, %a2
+    lea.l   .swapmask, %a3
+
+    move.l  %a0, %d0
+    btst.l  #0, %d0         /* 16-bit aligned? */
+    jeq     .r_aligned      /* yes, do word copy */
+
+    /* not 16-bit aligned */
+    subq.l  #1, %a1         /* last byte is done unconditionally */
+    moveq.l #24, %d1        /* preload shift count */
+
+    move.w  (%a2), %d2      /* load initial word */
+    move.b  %d2, (%a0)+     /* write high byte of it, aligns dest addr */
+                            /* we have byte swapped */
+
+    btst.l  #1, %d0         /* longword aligned? (testing old d0 value!) */
+    bne.b   .r_end_u_w1     /* yes, skip leading word handling */
+
+    swap    %d2             /* move initial word up */
+    move.w  (%a2), %d2      /* combine with second word */
+
+    /* byte swap d2 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d2, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d2        /* d2 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d2         /* d2 = .A.C */
+    or.l    %d7, %d2        /* d2 = BADC */
+
+    move.l  %d2, %d3
+    lsr.l   #8, %d3
+    move.w  %d3, (%a0)+     /* write bytes 2 and 3 as word */
+
+.r_end_u_w1:
+    moveq.l #12, %d0
+    add.l   %a0, %d0
+    and.l   #0xFFFFFFF0,%d0 /* d0 == first line bound */
+    cmp.l   %a0, %d0        /* any leading longwords? */
+    bls.b   .r_end_u_l1     /* no: skip loop */
+        
+.r_loop_u_l1:
+    move.w  (%a2), %d3      /* load first word */
+    swap    %d3             /* move to upper 16 bit */
+    move.w  (%a2), %d3      /* load second word */
+
+    /* byte swap d3 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d3, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d3        /* d3 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d3         /* d3 = .A.C */
+    or.l    %d7, %d3        /* d3 = BADC */
+
+    move.l  %d3, %d4
+    lsl.l   %d1, %d2
+    lsr.l   #8, %d3
+    or.l    %d3, %d2        /* combine old low byte with new top 3 bytes */
+    move.l  %d2, (%a0)+     /* store as long */
+    move.l  %d4, %d2
+    cmp.l   %a0, %d0        /* run up to first line bound */
+    bhi.b   .r_loop_u_l1
+
+.r_end_u_l1:
+    lea.l   (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */
+
+.r_loop_u_line:
+    move.w  (%a2), %d3      /* load 1st word */
+    swap    %d3             /* move to upper 16 bit */
+    move.w  (%a2), %d3      /* load 2nd word */
+
+    /* byte swap d3 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d3, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d3        /* d3 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d3         /* d3 = .A.C */
+    or.l    %d7, %d3        /* d3 = BADC */
+
+    move.l  %d3, %d0
+    lsl.l   %d1, %d2
+    lsr.l   #8, %d0
+    or.l    %d0, %d2        /* combine old low byte with new top 3 bytes */
+    move.w  (%a2), %d4      /* load 3rd word */
+    swap    %d4             /* move to upper 16 bit */
+    move.w  (%a2), %d4      /* load 4th word */
+
+    /* byte swap d4 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d4, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d4        /* d4 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d4         /* d4 = .A.C */
+    or.l    %d7, %d4        /* d4 = BADC */
+
+    move.l  %d4, %d0
+    lsl.l   %d1, %d3
+    lsr.l   #8, %d0
+    or.l    %d0, %d3        /* combine old low byte with new top 3 bytes */
+    move.w  (%a2), %d5      /* load 5th word */
+    swap    %d5             /* move to upper 16 bit */
+    move.w  (%a2), %d5      /* load 6th word */
+
+    /* byte swap d5 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d5, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d5        /* d5 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d5         /* d5 = .A.C */
+    or.l    %d7, %d5        /* d5 = BADC */
+
+    move.l  %d5, %d0
+    lsl.l   %d1, %d4
+    lsr.l   #8, %d0
+    or.l    %d0, %d4        /* combine old low byte with new top 3 bytes */
+    move.w  (%a2), %d6      /* load 7th word */
+    swap    %d6             /* move to upper 16 bit */
+    move.w  (%a2), %d6      /* load 8th word */
+
+    /* byte swap d6 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d6, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d6        /* d6 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d6         /* d6 = .A.C */
+    or.l    %d7, %d6        /* d6 = BADC */
+
+    move.l  %d6, %d0
+    lsl.l   %d1, %d5
+    lsr.l   #8, %d0
+    or.l    %d0, %d5        /* combine old low byte with new top 3 bytes */
+    movem.l %d2-%d5, (%a0)  /* store line */
+    lea.l   (16, %a0), %a0
+    move.l  %d6, %d2
+    cmp.l   %a0, %a1        /* run up to last line bound */
+    bhi.b   .r_loop_u_line
+
+    lea.l   (12, %a1), %a1  /* readjust for longword loop */
+    cmp.l   %a0, %a1        /* any trailing longwords? */
+    bls.b   .r_end_u_l2     /* no: skip loop */
+
+.r_loop_u_l2:
+    move.w  (%a2), %d3      /* load first word */
+    swap    %d3             /* move to upper 16 bit */
+    move.w  (%a2), %d3      /* load second word */
+
+    /* byte swap d3 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d3, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d3        /* d3 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d3         /* d3 = .A.C */
+    or.l    %d7, %d3        /* d3 = BADC */
+
+    move.l  %d3, %d4
+    lsl.l   %d1, %d2
+    lsr.l   #8, %d3
+    or.l    %d3, %d2        /* combine old low byte with new top 3 bytes */
+    move.l  %d2, (%a0)+     /* store as long */
+    move.l  %d4, %d2
+    cmp.l   %a0, %a1        /* run up to last long bound */
+    bhi.b   .r_loop_u_l2
+        
+.r_end_u_l2:
+    addq.l  #2, %a1         /* back to final end address */
+    cmp.l   %a0, %a1        /* one word left? */
+    bls.b   .r_end_u_w2
+
+    swap    %d2             /* move old word to upper 16 bits */
+    move.w  (%a2), %d2      /* load final word */
+
+    /* byte swap d2 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d2, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d2        /* d2 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d2         /* d2 = .A.C */
+    or.l    %d7, %d2        /* d2 = BADC */
+
+    move.l  %d2, %d3
+    lsr.l   #8, %d3
+    move.w  %d3, (%a0)+     /* write bytes 2 and 3 as word */
+
+.r_end_u_w2:
+    move.b  %d2, (%a0)+     /* store final byte */
+    bra.w   .r_exit
+
+    /* 16-bit aligned */
+.r_aligned:
+    btst.l  #1, %d0         /* longword aligned? */
+    beq.b   .r_end_a_w1     /* yes, skip leading word handling */
+
+    /* copy initial word */
+    /* initial word has to be swapped */
+    move.w  (%a2), %d7
+    move.b  %d7, (%a0)+
+    lsr.l   #8, %d7
+    move.b  %d7, (%a0)+
+
+.r_end_a_w1:
+    moveq.l #12, %d0
+    add.l   %a0, %d0
+    and.l   #0xFFFFFFF0,%d0 /* d0 == first line bound */
+    cmp.l   %a0, %d0        /* any leading longwords? */
+    bls.b   .r_end_a_l1     /* no: skip loop */
+
+.r_loop_a_l1:
+    move.w  (%a2), %d1      /* load first word */
+    swap    %d1             /* move it to upper 16 bits */
+    move.w  (%a2), %d1      /* load second word */
+
+    /* byte swap d1 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d1, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d1        /* d1 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d1         /* d1 = .A.C */
+    or.l    %d7, %d1        /* d1 = BADC */
+
+    move.l  %d1, (%a0)+     /* store as long */
+    cmp.l   %a0, %d0        /* run up to first line bound */
+    bhi.b   .r_loop_a_l1
+
+.r_end_a_l1:
+    lea.l   (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */
+
+.r_loop_a_line:
+    move.w  (%a2), %d0      /* load 1st word */
+    swap    %d0             /* move it to upper 16 bits */
+    move.w  (%a2), %d0      /* load 2nd word */
+
+    /* byte swap d0 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d0, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d0        /* d0 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d0         /* d0 = .A.C */
+    or.l    %d7, %d0        /* d0 = BADC */
+
+    move.w  (%a2), %d1      /* load 3rd word */
+    swap    %d1             /* move it to upper 16 bits */
+    move.w  (%a2), %d1      /* load 4th word */
+
+    /* byte swap d1 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d1, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d1        /* d1 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d1         /* d1 = .A.C */
+    or.l    %d7, %d1        /* d1 = BADC */
+
+    move.w  (%a2), %d2      /* load 5th word */
+    swap    %d2             /* move it to upper 16 bits */
+    move.w  (%a2), %d2      /* load 6th word */
+
+    /* byte swap d2 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d2, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d2        /* d2 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d2         /* d2 = .A.C */
+    or.l    %d7, %d2        /* d2 = BADC */
+
+    move.w  (%a2), %d3      /* load 7th word */
+    swap    %d3             /* move it to upper 16 bits */
+    move.w  (%a2), %d3      /* load 8th word */
+
+    /* byte swap d3 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d3, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d3        /* d3 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d3         /* d3 = .A.C */
+    or.l    %d7, %d3        /* d3 = BADC */
+
+    movem.l %d0-%d3, (%a0)  /* store line */
+    lea.l   (16, %a0), %a0
+    cmp.l   %a0, %a1        /* run up to last line bound */
+    bhi.b   .r_loop_a_line
+
+    lea.l   (12, %a1), %a1  /* readjust for longword loop */
+    cmp.l   %a0, %a1        /* any trailing longwords? */
+    bls.b   .r_end_a_l2     /* no: skip loop */
+
+.r_loop_a_l2:
+    move.w  (%a2), %d1      /* read first word */
+    swap    %d1             /* move it to upper 16 bits */
+    move.w  (%a2), %d1      /* read second word */
+
+    /* byte swap d1 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d1, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d1        /* d1 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d1         /* d1 = .A.C */
+    or.l    %d7, %d1        /* d1 = BADC */
+
+    move.l  %d1, (%a0)+     /* store as long */
+    cmp.l   %a0, %a1        /* run up to last long bound */
+    bhi.b   .r_loop_a_l2
+        
+.r_end_a_l2:
+    addq.l  #2, %a1         /* back to final end address */
+    cmp.l   %a0, %a1        /* one word left? */
+    bls.b   .r_end_a_w2
+
+    /* copy final word */
+    /* final word has to be swapped */
+    move.w (%a2), %d7
+    move.b %d7, (%a0)+
+    lsr.l  #8, %d7
+    move.b %d7, (%a0)+
+
+.r_end_a_w2:
+
+.r_exit:
+    movem.l (%sp), %d2-%d7/%a2-%a3
+    lea.l   (32, %sp), %sp
+    rts
+
+.r_end:
+    .size   copy_read_sectors,.r_end-copy_read_sectors
+
+    .align  2
+    .global copy_write_sectors
+    .type   copy_write_sectors,@function
+
+#if 0
+/* Write a number of words to the ATA data port
+ *
+ * Utilises line bursts, assumes there is at least one full line to copy.
+ *
+ * Arguments:
+ *   (4,%sp) - buffer address
+ *   (8,%sp) - word count
+ *
+ * Register usage:
+ *   %a0 - current address
+ *   %a1 - end address
+ *   %a2 - ata port
+ *   %d0 - scratch
+ *   %d1 - shift count
+ *   %d2-%d6 - read buffers
+ *
+ *   %d7 - swap scrach
+ *   %a3 - swap mask
+ */
+
+copy_write_sectors:
+    lea.l   (-32, %sp), %sp
+    movem.l %d2-%d7/%a2-%a3, (%sp)
+    movem.l (36, %sp), %a0-%a1
+    add.l   %a1, %a1
+    add.l   %a0, %a1
+    lea.l   .ata_port, %a2
+    lea.l   .swapmask, %a3
+
+    move.l  %a0, %d0
+    btst.l  #0, %d0         /* 16-bit aligned? */
+    beq     .w_aligned      /* yes, do word copy */
+
+    /* not 16-bit aligned */
+    subq.l  #1, %a1         /* last byte is done unconditionally */
+    moveq.l #24, %d1        /* preload shift count */
+
+    move.b  (%a0)+, %d2
+
+    btst.l  #1, %d0         /* longword aligned? (testing old d0 value!) */
+    bne.b   .w_end_u_w1     /* yes, skip leading word handling */
+
+    swap    %d2
+    move.w  (%a0)+, %d2
+    move.l  %d2, %d3
+    lsr.l   #8, %d3
+
+    /* low word of %d3 has to be byte swaped */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d3, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d3        /* d3 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d3         /* d3 = .A.C */
+    or.l    %d7, %d3        /* d3 = BADC */
+
+   move.w %d3, (%a2)
+        
+.w_end_u_w1:
+    moveq.l #12, %d0
+    add.l   %a0, %d0
+    and.l   #0xFFFFFFF0,%d0 /* d0 == first line bound */
+    cmp.l   %a0, %d0        /* any leading longwords? */
+    bls.b   .w_end_u_l1     /* no: skip loop */
+        
+.w_loop_u_l1:
+    move.l  (%a0)+, %d3
+    move.l  %d3, %d4
+    lsl.l   %d1, %d2
+    lsr.l   #8, %d3
+    or.l    %d3, %d2
+
+    /* byte swap d2 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d2, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d2        /* d2 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d2         /* d2 = .A.C */
+    or.l    %d7, %d2        /* d2 = BADC */
+
+    swap    %d2
+    move.w  %d2, (%a2)
+    swap    %d2
+    move.w  %d2, (%a2)
+    move.l  %d4, %d2
+    cmp.l   %a0, %d0        /* run up to first line bound */
+    bhi.b   .w_loop_u_l1
+
+.w_end_u_l1:
+    lea.l   (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */
+
+.w_loop_u_line:
+    movem.l (%a0), %d3-%d6
+    lea.l   (16, %a0), %a0
+    move.l  %d3, %d0
+    lsl.l   %d1, %d2
+    lsr.l   #8, %d0
+    or.l    %d0, %d2
+
+    /* byte swap d2 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d2, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d2        /* d2 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d2         /* d2 = .A.C */
+    or.l    %d7, %d2        /* d2 = BADC */
+
+    swap    %d2
+    move.w  %d2, (%a2)
+    swap    %d2
+    move.w  %d2, (%a2)
+    move.l  %d4, %d0
+    lsl.l   %d1, %d3
+    lsr.l   #8, %d0
+    or.l    %d0, %d3
+
+    /* byte swap d3 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d3, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d3        /* d3 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d3         /* d3 = .A.C */
+    or.l    %d7, %d3        /* d3 = BADC */
+
+    swap    %d3
+    move.w  %d3, (%a2)
+    swap    %d3
+    move.w  %d3, (%a2)
+    move.l  %d5, %d0
+    lsl.l   %d1, %d4
+    lsr.l   #8, %d0
+    or.l    %d0, %d4
+
+    /* byte swap d4 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d4, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d4        /* d4 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d4         /* d4 = .A.C */
+    or.l    %d7, %d4        /* d4 = BADC */
+
+    swap    %d4
+    move.w  %d4, (%a2)
+    swap    %d4
+    move.w  %d4, (%a2)
+    move.l  %d6, %d0
+    lsl.l   %d1, %d5
+    lsr.l   #8, %d0
+    or.l    %d0, %d5
+
+    /* byte swap d5 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d5, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d5        /* d5 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d5         /* d5 = .A.C */
+    or.l    %d7, %d5        /* d5 = BADC */
+
+    swap    %d5
+    move.w  %d5, (%a2)
+    swap    %d5
+    move.w  %d5, (%a2)
+    move.l  %d6, %d2
+    cmp.l   %a0, %a1        /* run up to last line bound */
+    bhi.b   .w_loop_u_line
+
+    lea.l   (12, %a1), %a1  /* readjust for longword loop */
+    cmp.l   %a0, %a1        /* any trailing longwords? */
+    bls.b   .w_end_u_l2     /* no: skip loop */
+
+.w_loop_u_l2:
+    move.l  (%a0)+, %d3
+    move.l  %d3, %d4
+    lsl.l   %d1, %d2
+    lsr.l   #8, %d3
+    or.l    %d3, %d2
+
+    /* byte swap d2 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d2, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d2        /* d2 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d2         /* d2 = .A.C */
+    or.l    %d7, %d2        /* d2 = BADC */
+
+    swap    %d2
+    move.w  %d2, (%a2)
+    swap    %d2
+    move.w  %d2, (%a2)
+    move.l  %d4, %d2
+    cmp.l   %a0, %a1        /* run up to first line bound */
+    bhi.b   .w_loop_u_l2
+
+.w_end_u_l2:
+    addq.l  #2, %a1         /* back to final end address */
+    cmp.l   %a0, %a1        /* one word left? */
+    bls.b   .w_end_u_w2
+
+    swap    %d2
+    move.w  (%a0)+, %d2
+    move.l  %d2, %d3
+    lsr.l   #8, %d3
+
+    /* byte swap d3 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d3, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d3        /* d3 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d3         /* d3 = .A.C */
+    or.l    %d7, %d3        /* d3 = BADC */
+
+    move.w  %d3, (%a2)
+
+.w_end_u_w2:
+    lsl.l   #8, %d2
+    move.b  (%a0)+, %d2
+
+    /* byte swap d2 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d2, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d2        /* d2 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d2         /* d2 = .A.C */
+    or.l    %d7, %d2        /* d2 = BADC */
+
+    move.w  %d2, (%a2)
+    bra.w    .w_exit
+
+    /* 16-bit aligned */
+.w_aligned:
+    btst.l  #1, %d0
+    beq.b   .w_end_a_w1
+
+    /* this has to be byte swaped */
+    /* copy initial word */
+    move.w  (%a0)+, %d1
+
+    /* byte swap d1 */
+    move.l  %a3, %d7        /* d7 = $00FF00FF */
+    and.l   %d1, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d1        /* d1 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d1         /* d1 = .A.C */
+    or.l    %d7, %d1        /* d1 = BADC */
+
+    move.w  %d1, (%a2)
+
+
+.w_end_a_w1:
+    moveq.l #12, %d0
+    add.l   %a0, %d0
+    and.l   #0xFFFFFFF0,%d0 /* d0 == first line bound */
+    cmp.l   %a0, %d0        /* any leading longwords? */
+    bls.b   .w_end_a_l1     /* no: skip loop */
+
+.w_loop_a_l1:
+    move.l  (%a0)+, %d1
+
+/* byte swap d1 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d1, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d1        /* d1 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d1         /* d1 = .A.C */
+    or.l    %d7, %d1        /* d1 = BADC */
+
+    swap    %d1
+    move.w  %d1, (%a2)
+    swap    %d1
+    move.w  %d1, (%a2)
+    cmp.l   %a0, %d0        /* run up to first line bound */
+    bhi.b   .w_loop_a_l1
+
+.w_end_a_l1:
+    lea.l   (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */
+
+.w_loop_a_line:
+    movem.l (%a0), %d0-%d3
+
+/* byte swap d0-d3 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d0, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d0        /* d0 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d0         /* d0 = .A.C */
+    or.l    %d7, %d0        /* d0 = BADC */
+
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d1, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d1        /* d1 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d1         /* d1 = .A.C */
+    or.l    %d7, %d1        /* d1 = BADC */
+
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d2, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d2        /* d2 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d2         /* d2 = .A.C */
+    or.l    %d7, %d2        /* d2 = BADC */
+
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d3, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d3        /* d3 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d3         /* d3 = .A.C */
+    or.l    %d7, %d3        /* d3 = BADC */
+
+    lea.l   (16, %a0), %a0
+    swap    %d0
+    move.w  %d0, (%a2)
+    swap    %d0
+    move.w  %d0, (%a2)
+    swap    %d1
+    move.w  %d1, (%a2)
+    swap    %d1
+    move.w  %d1, (%a2)
+    swap    %d2
+    move.w  %d2, (%a2)
+    swap    %d2
+    move.w  %d2, (%a2)
+    swap    %d3
+    move.w  %d3, (%a2)
+    swap    %d3
+    move.w  %d3, (%a2)
+    cmp.l   %a0, %a1        /* run up to last line bound */
+    bhi.b   .w_loop_a_line
+        
+    lea.l   (12, %a1), %a1  /* readjust for longword loop */
+    cmp.l   %a0, %a1        /* any trailing longwords? */
+    bls.b   .w_end_a_l2     /* no: skip loop */
+
+.w_loop_a_l2:
+    move.l  (%a0)+, %d1
+
+/* byte swap d1 */
+    move.l  %a3, %d7        /* d7 = 0x00FF00FF */
+    and.l   %d1, %d7        /* d7 = .B.D */
+    eor.l   %d7, %d1        /* d1 = A.C. */
+    lsl.l   #8, %d7         /* d7 = B.D. */
+    lsr.l   #8, %d1         /* d1 = .A.C */
+    or.l    %d7, %d1        /* d1 = BADC */
+
+    swap    %d1
+    move.w  %d1, (%a2)
+    swap    %d1
+    move.w  %d1, (%a2)
+    cmp.l   %a0, %a1        /* run up to first line bound */
+    bhi.b   .w_loop_a_l2
+
+.w_end_a_l2:
+    addq.l  #2, %a1         /* back to final end address */
+    cmp.l   %a0, %a1        /* one word left? */
+    bls.b   .w_end_a_w2
+
+/* this has to be byte swaped */
+/* copy final word */
+    move.w (%a0)+, %d0
+    move.l %a3, %d7
+    and.l  %d0, %d7
+    eor.l  %d7, %d0
+    lsl.l  #8, %d7
+    lsr.l  #8, %d0
+    or.l   %d7, %d0
+    move.w %d0, (%a2) 
+
+.w_end_a_w2:
+
+.w_exit:
+    movem.l (%sp), %d2-%d7/%a2-%a3
+    lea.l   (32, %sp), %sp
+    rts
+
+.w_end:
+    .size   copy_write_sectors,.w_end-copy_write_sectors
+#endif
diff --git a/firmware/target/coldfire/mpio/ata-mpio.c b/firmware/target/coldfire/mpio/ata-mpio.c
new file mode 100644
index 0000000..ca1c9b1
--- /dev/null
+++ b/firmware/target/coldfire/mpio/ata-mpio.c
@@ -0,0 +1,57 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "cpu.h"
+#include <stdbool.h>
+#include "kernel.h"
+#include "system.h"
+#include "power.h"
+#include "ata-target.h"
+
+void ata_reset(void)
+{
+    /* GPIO19 */
+    and_l(~(1<<19), &GPIO_OUT);
+    sleep(1); /* > 25us */
+
+    or_l((1<<19), &GPIO_OUT);
+    sleep(1); /* > 25us */
+}
+
+void ata_enable(bool on)
+{
+    (void)on;
+}
+
+/* to be fixed */
+bool ata_is_coldstart(void)
+{
+    return true;
+}
+
+void ata_device_init(void)
+{
+    /* ATA reset line config */
+    or_l((1<<19), &GPIO_OUT);
+    or_l((1<<19), &GPIO_ENABLE);
+    or_l((1<<19), &GPIO_FUNCTION);
+}
diff --git a/firmware/target/coldfire/mpio/ata-target.h b/firmware/target/coldfire/mpio/ata-target.h
new file mode 100644
index 0000000..1fa4c5a
--- /dev/null
+++ b/firmware/target/coldfire/mpio/ata-target.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef ATA_TARGET_H
+#define ATA_TARGET_H
+
+/* asm optimised read & write loops - we skip this for now*/
+#define ATA_OPTIMIZED_READING
+//#define ATA_OPTIMIZED_WRITING
+
+#define SWAP_WORDS
+
+#define ATA_IOBASE      0x20000000
+#define ATA_DATA        (*((volatile unsigned short*)(ATA_IOBASE + 0x20)))
+#define ATA_CONTROL     (*((volatile unsigned short*)(ATA_IOBASE + 0x1c)))
+
+#define ATA_ERROR       (*((volatile unsigned short*)(ATA_IOBASE + 0x22)))
+#define ATA_NSECTOR     (*((volatile unsigned short*)(ATA_IOBASE + 0x24)))
+#define ATA_SECTOR      (*((volatile unsigned short*)(ATA_IOBASE + 0x26)))
+#define ATA_LCYL        (*((volatile unsigned short*)(ATA_IOBASE + 0x28)))
+#define ATA_HCYL        (*((volatile unsigned short*)(ATA_IOBASE + 0x2a)))
+#define ATA_SELECT      (*((volatile unsigned short*)(ATA_IOBASE + 0x2c)))
+#define ATA_COMMAND     (*((volatile unsigned short*)(ATA_IOBASE + 0x2e)))
+
+
+#define STATUS_BSY     0x80
+#define STATUS_RDY     0x40
+#define STATUS_DF      0x20
+#define STATUS_DRQ     0x08
+#define STATUS_ERR     0x01
+
+#define ERROR_ABRT     0x04
+#define ERROR_IDNF     0x10
+
+#define WRITE_PATTERN1 0xa5
+#define WRITE_PATTERN2 0x5a
+#define WRITE_PATTERN3 0xaa
+#define WRITE_PATTERN4 0x55
+
+#define READ_PATTERN1  0xa5
+#define READ_PATTERN2  0x5a
+#define READ_PATTERN3  0xaa
+#define READ_PATTERN4  0x55
+
+#define READ_PATTERN1_MASK 0xff
+#define READ_PATTERN2_MASK 0xff
+#define READ_PATTERN3_MASK 0xff
+#define READ_PATTERN4_MASK 0xff
+
+#define SET_REG(reg,val) reg = (val)
+#define SET_16BITREG(reg,val) reg = (val)
+
+void ata_reset(void);
+void ata_enable(bool on);
+void ata_device_init(void);
+bool ata_is_coldstart(void);
+
+void copy_read_sectors(unsigned char* buf, int wordcount);
+//void copy_write_sectors(const unsigned char* buf, int wordcount);
+#endif
diff --git a/firmware/target/coldfire/mpio/audio-mpio.c b/firmware/target/coldfire/mpio/audio-mpio.c
new file mode 100644
index 0000000..28c6419
--- /dev/null
+++ b/firmware/target/coldfire/mpio/audio-mpio.c
@@ -0,0 +1,49 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "system.h"
+#include "cpu.h"
+#include "audio.h"
+#include "sound.h"
+
+void audio_set_output_source(int source)
+{
+
+    (void)source;
+    int level = set_irq_level(DMA_IRQ_LEVEL);
+
+    /* PDOR3 */
+    IIS2CONFIG = (IIS2CONFIG & ~(7 << 8)) | (3 << 8);
+
+    restore_irq(level);
+}
+
+void audio_input_mux(int source, unsigned flags)
+{
+    (void)source;
+    (void)flags;
+
+    switch(source)
+    {
+        case AUDIO_SRC_FMRADIO:
+        break;
+    }
+    /* empty stub */
+}
diff --git a/firmware/target/coldfire/mpio/boot.lds b/firmware/target/coldfire/mpio/boot.lds
new file mode 100644
index 0000000..2b08658
--- /dev/null
+++ b/firmware/target/coldfire/mpio/boot.lds
@@ -0,0 +1,81 @@
+#include "config.h"
+
+ENTRY(start)
+OUTPUT_FORMAT(elf32-m68k)
+STARTUP(target/coldfire/crt0.o)
+
+#define DRAMSIZE (MEMORYSIZE * 0x100000)
+
+#define DRAMORIG 0x31000000
+#define IRAMORIG 0x10000000
+#define IRAMSIZE 0x18000
+#define FLASHORIG 0x000e0000
+#define FLASHSIZE 0x1f800
+
+MEMORY
+{
+   DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
+   IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
+   FLASH : ORIGIN = FLASHORIG, LENGTH = FLASHSIZE
+}
+
+SECTIONS
+{
+    .vectors :
+    {
+        _datacopy = .;
+    } > FLASH
+
+    .data : AT ( _datacopy )
+    {
+        _datastart = .;
+        KEEP(*(.resetvectors));
+        *(.resetvectors);
+        KEEP(*(.vectors));
+        *(.vectors);
+        . = ALIGN(0x200);
+        *(.icode)
+        *(.irodata)
+        *(.idata)
+        *(.data*)
+        . = ALIGN(0x4);
+        _dataend = .;
+        . = ALIGN(0x10);  /* Maintain proper alignment for .text section */
+    } > IRAM
+
+    /* TRICK ALERT! Newer versions of the linker don't allow output sections
+       to overlap even if one of them is empty, so advance the location pointer
+       "by hand" */
+    .text LOADADDR(.data) + SIZEOF(.data) :
+    {
+        *(.init.text)
+        *(.text*)
+        . = ALIGN(0x4);
+    } > FLASH
+
+    .rodata :
+    {
+        *(.rodata*)
+        . = ALIGN(0x4);
+        _iramcopy = .;
+    } > FLASH
+
+    .stack :
+    {
+       *(.stack)
+       _stackbegin = .;
+       stackbegin = .;
+       . += 0x2000;
+       _stackend = .;
+       stackend = .;
+    } > IRAM
+
+    .bss DRAMORIG+0x800000:
+    {
+       _edata = .;
+        *(.ibss)
+        *(.bss*)
+        *(COMMON)
+       _end = .;
+    } > DRAM
+}
diff --git a/firmware/target/coldfire/mpio/boot.lds.flash b/firmware/target/coldfire/mpio/boot.lds.flash
new file mode 100644
index 0000000..2b08658
--- /dev/null
+++ b/firmware/target/coldfire/mpio/boot.lds.flash
@@ -0,0 +1,81 @@
+#include "config.h"
+
+ENTRY(start)
+OUTPUT_FORMAT(elf32-m68k)
+STARTUP(target/coldfire/crt0.o)
+
+#define DRAMSIZE (MEMORYSIZE * 0x100000)
+
+#define DRAMORIG 0x31000000
+#define IRAMORIG 0x10000000
+#define IRAMSIZE 0x18000
+#define FLASHORIG 0x000e0000
+#define FLASHSIZE 0x1f800
+
+MEMORY
+{
+   DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
+   IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
+   FLASH : ORIGIN = FLASHORIG, LENGTH = FLASHSIZE
+}
+
+SECTIONS
+{
+    .vectors :
+    {
+        _datacopy = .;
+    } > FLASH
+
+    .data : AT ( _datacopy )
+    {
+        _datastart = .;
+        KEEP(*(.resetvectors));
+        *(.resetvectors);
+        KEEP(*(.vectors));
+        *(.vectors);
+        . = ALIGN(0x200);
+        *(.icode)
+        *(.irodata)
+        *(.idata)
+        *(.data*)
+        . = ALIGN(0x4);
+        _dataend = .;
+        . = ALIGN(0x10);  /* Maintain proper alignment for .text section */
+    } > IRAM
+
+    /* TRICK ALERT! Newer versions of the linker don't allow output sections
+       to overlap even if one of them is empty, so advance the location pointer
+       "by hand" */
+    .text LOADADDR(.data) + SIZEOF(.data) :
+    {
+        *(.init.text)
+        *(.text*)
+        . = ALIGN(0x4);
+    } > FLASH
+
+    .rodata :
+    {
+        *(.rodata*)
+        . = ALIGN(0x4);
+        _iramcopy = .;
+    } > FLASH
+
+    .stack :
+    {
+       *(.stack)
+       _stackbegin = .;
+       stackbegin = .;
+       . += 0x2000;
+       _stackend = .;
+       stackend = .;
+    } > IRAM
+
+    .bss DRAMORIG+0x800000:
+    {
+       _edata = .;
+        *(.ibss)
+        *(.bss*)
+        *(COMMON)
+       _end = .;
+    } > DRAM
+}
diff --git a/firmware/target/coldfire/mpio/boot.lds.iram b/firmware/target/coldfire/mpio/boot.lds.iram
new file mode 100644
index 0000000..769e102
--- /dev/null
+++ b/firmware/target/coldfire/mpio/boot.lds.iram
@@ -0,0 +1,81 @@
+#include "config.h"
+
+ENTRY(start)
+OUTPUT_FORMAT(elf32-m68k)
+STARTUP(target/coldfire/crt0.o)
+
+#define DRAMSIZE (MEMORYSIZE * 0x100000)
+
+#define DRAMORIG 0x31000000
+#define IRAMORIG 0x10000000
+#define IRAMSIZE 0x18000
+#define FLASHORIG 0x000e0000
+#define FLASHSIZE 0x1f800
+
+MEMORY
+{
+   DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
+   IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
+   FLASH : ORIGIN = FLASHORIG, LENGTH = FLASHSIZE
+}
+
+SECTIONS
+{
+    .vectors :
+    {
+        _datacopy = .;
+    } > IRAM
+
+    .data : AT ( _datacopy )
+    {
+        _datastart = .;
+        KEEP(*(.resetvectors));
+        *(.resetvectors);
+        KEEP(*(.vectors));
+        *(.vectors);
+        . = ALIGN(0x200);
+        *(.icode)
+        *(.irodata)
+        *(.idata)
+        *(.data*)
+        . = ALIGN(0x4);
+        _dataend = .;
+        . = ALIGN(0x10);  /* Maintain proper alignment for .text section */
+    } > IRAM
+
+    /* TRICK ALERT! Newer versions of the linker don't allow output sections
+       to overlap even if one of them is empty, so advance the location pointer
+       "by hand" */
+    .text LOADADDR(.data) + SIZEOF(.data) :
+    {
+        *(.init.text)
+        *(.text*)
+        . = ALIGN(0x4);
+    } > IRAM
+
+    .rodata :
+    {
+        *(.rodata*)
+        . = ALIGN(0x4);
+        _iramcopy = .;
+    } > IRAM
+
+    .stack :
+    {
+       *(.stack)
+       _stackbegin = .;
+       stackbegin = .;
+       . += 0x2000;
+       _stackend = .;
+       stackend = .;
+    } > IRAM
+
+    .bss DRAMORIG+0x800000:
+    {
+       _edata = .;
+        *(.ibss)
+        *(.bss*)
+        *(COMMON)
+       _end = .;
+    } > DRAM
+}
diff --git a/firmware/target/coldfire/mpio/button-target.h b/firmware/target/coldfire/mpio/button-target.h
new file mode 100644
index 0000000..ae55612
--- /dev/null
+++ b/firmware/target/coldfire/mpio/button-target.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _BUTTON_TARGET_H_
+#define _BUTTON_TARGET_H_
+
+#include <stdbool.h>
+#include "config.h"
+
+#define HAS_BUTTON_HOLD
+
+bool button_hold(void);
+void button_init_device(void);
+int button_read_device(void);
+
+/* HD200 specific button codes */
+/* Main unit's buttons  - flags as in original firmware*/
+#define BUTTON_PLAY         0x00000001
+
+#define BUTTON_PREV         0x00000004
+#define BUTTON_NEXT         0x00000002
+#define BUTTON_VOL_UP       0x00000008
+#define BUTTON_VOL_DOWN     0x00000010
+#define BUTTON_REC          0x00000020
+#define BUTTON_SELECT       0x00002000
+
+#define BUTTON_LEFT BUTTON_PREV
+#define BUTTON_RIGHT BUTTON_NEXT
+#define BUTTON_ON BUTTON_PLAY
+#define BUTTON_REMOTE 0x0
+
+#define BUTTON_MAIN (BUTTON_PLAY|BUTTON_PREV|BUTTON_NEXT|BUTTON_VOL_UP|\
+        BUTTON_VOL_DOWN|BUTTON_REC|BUTTON_SELECT)
+
+#define POWEROFF_BUTTON BUTTON_PLAY
+#define POWEROFF_COUNT 30
+
+#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/coldfire/mpio/fmradio_i2c-mpio.c b/firmware/target/coldfire/mpio/fmradio_i2c-mpio.c
new file mode 100644
index 0000000..a687c13
--- /dev/null
+++ b/firmware/target/coldfire/mpio/fmradio_i2c-mpio.c
@@ -0,0 +1,40 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ * Physical interface of the Philips TEA5767 in iAudio M3
+ *
+ * Copyright (C) 2002 by Linus Nielsen Feltzing
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+
+#if (CONFIG_TUNER & TEA5767)
+
+#include "i2c-coldfire.h"
+#include "fmradio_i2c.h"
+
+int fmradio_i2c_write(unsigned char address, const unsigned char* buf,
+                      int count)
+{
+    return i2c_write(I2C_IFACE_1, address, buf, count);
+}
+
+int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
+{
+    return i2c_read(I2C_IFACE_1, address, buf, count);
+}
+
+#endif
diff --git a/firmware/target/coldfire/mpio/hd200/adc-hd200.c b/firmware/target/coldfire/mpio/hd200/adc-hd200.c
new file mode 100644
index 0000000..8bf9643
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/adc-hd200.c
@@ -0,0 +1,84 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "cpu.h"
+#include "system.h"
+#include "kernel.h"
+#include "thread.h"
+#include "adc.h"
+
+volatile unsigned short adc_data[NUM_ADC_CHANNELS] IBSS_ATTR;
+
+/* Reading takes 4096 adclk ticks
+ * We do read one channel at once
+ * 
+ * state      FCPU         Fbus        Fadc      bus/Fadc   Fchannelread
+ * default 11.2896 MHz  5.6448 MHz  5.6448 MHz      2       172.2656 Hz
+ * normal  45.1584 MHz  22.5792 MHz 2.8224 MHz      8       172.2656 Hz
+ * max     124.1856 MHz 62.0928 MHz 1.9404 MHz      32      118.4326 Hz
+ */
+
+void ADC(void) __attribute__ ((interrupt_handler,section(".icode")));
+void ADC(void)
+{
+    static unsigned char channel;
+    /* read current value */
+    adc_data[(channel & 0x03)] = ADVALUE;
+
+    /* switch channel
+     *
+     * set source remark
+     * ADCONFIG is 16bit wide so we have to shift data by 16bits left
+     * thats why we shift <<24 instead of <<8
+     */
+
+    channel++;
+
+    and_l(~(3<<24),&ADCONFIG);
+    or_l( (((channel & 0x03) << 8 )|(1<<7))<<16, &ADCONFIG);
+
+}
+
+unsigned short adc_scan(int channel)
+{
+    /* maybe we can drop &0x03 part */
+    return adc_data[(channel&0x03)];
+}
+
+void adc_init(void)
+{
+    /* GPIO38 GPIO39 */
+    and_l(~((1<<6)|(1<<7)), &GPIO1_FUNCTION);
+
+    /* ADOUT_SEL = 01
+     * SOURCE SELECT = 000
+     * CLEAR INTERRUPT FLAG
+     * ENABLE INTERRUPT = 1
+     * ADOUT_DRIVE = 00
+     * ADCLK_SEL = 011 (busclk/8)
+     */
+
+    ADCONFIG = (1<<10)|(1<<7)|(1<<6)|(1<<1)|(1<<0);
+
+    /* ADC interrupt level 4.0 */
+    or_l((4<<28), &INTPRI8);
+}
diff --git a/firmware/target/coldfire/mpio/hd200/adc-target.h b/firmware/target/coldfire/mpio/hd200/adc-target.h
new file mode 100644
index 0000000..2e61065
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/adc-target.h
@@ -0,0 +1,41 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _ADC_TARGET_H_
+#define _ADC_TARGET_H_
+
+#define NUM_ADC_CHANNELS  4
+
+#define ADC_BUTTONS       1
+#define ADC_REMOTE        0
+#define ADC_BATTERY       2
+#define ADC_REMOTEDETECT  3
+#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
+
+/* Force a scan now */
+unsigned short adc_scan(int channel);
+
+static inline unsigned short adc_read(int channel)
+{ 
+    return adc_scan(channel); 
+}
+
+#endif /* _ADC_TARGET_H_ */
diff --git a/firmware/target/coldfire/mpio/hd200/backlight-hd200.c b/firmware/target/coldfire/mpio/hd200/backlight-hd200.c
new file mode 100644
index 0000000..783376c
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/backlight-hd200.c
@@ -0,0 +1,86 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "cpu.h"
+#include "kernel.h"
+#include "system.h"
+#include "backlight.h"
+#include "backlight-target.h"
+#include "lcd.h"
+
+static bool _backlight_on = false;
+static int _brightness = DEFAULT_BRIGHTNESS_SETTING;
+
+/* Returns the current state of the backlight (true=ON, false=OFF). */
+bool _backlight_init(void)
+{
+    and_l(~(1<<28),&GPIO_OUT);
+    or_l((1<<28),&GPIO_FUNCTION);
+    or_l((1<<28),&GPIO_ENABLE);
+    return true;
+}
+
+void _backlight_hw_on(void)
+{
+
+    if (_backlight_on)
+        return;
+   
+    _backlight_set_brightness(_brightness);
+    _backlight_on = true;
+
+}
+
+void _backlight_hw_off(void)
+{
+    /* GPIO28 low */
+    and_l(~(1<<28),&GPIO_OUT);
+    _backlight_on = false;
+}
+
+void _backlight_set_brightness(int val)
+{
+    unsigned char i;
+
+    and_l(~(1<<28),&GPIO_OUT);
+    sleep(4);
+
+    for (i=0;i<val;i++)
+    {
+        or_l((1<<28),&GPIO_OUT);
+        and_l(~(1<<28),&GPIO_OUT);
+    }
+    
+    or_l((1<<28),&GPIO_OUT);
+
+    _brightness = val;
+}
+
+void _remote_backlight_on(void)
+{
+    /* I don't have remote to play with */
+}
+
+void _remote_backlight_off(void)
+{
+    /* I don't have remote to play with */
+}
diff --git a/firmware/target/coldfire/mpio/hd200/backlight-target.h b/firmware/target/coldfire/mpio/hd200/backlight-target.h
new file mode 100644
index 0000000..0080cca
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/backlight-target.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef BACKLIGHT_TARGET_H
+#define BACKLIGHT_TARGET_H
+
+bool _backlight_init(void); /* Returns backlight current state (true=ON). */
+void _backlight_hw_on(void);
+void _backlight_hw_off(void);
+void _backlight_set_brightness(int val);
+
+#define _backlight_on() _backlight_hw_on()
+#define _backlight_off() _backlight_hw_off()
+#define _backlight_on_isr() _backlight_hw_on()
+#define _backlight_off_isr() _backlight_hw_off()
+#define _backlight_on_normal() _backlight_hw_on()
+#define _backlight_off_normal() _backlight_hw_off()
+#endif
diff --git a/firmware/target/coldfire/mpio/hd200/button-hd200.c b/firmware/target/coldfire/mpio/hd200/button-hd200.c
new file mode 100644
index 0000000..b40c332
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/button-hd200.c
@@ -0,0 +1,123 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "cpu.h"
+#include "system.h"
+#include "button.h"
+#include "backlight.h"
+#include "adc.h"
+
+void button_init_device(void)
+{
+    /* Set GPIO36, GPIO56 as general purpose inputs */
+    or_l((1<<4)|(1<<24),&GPIO1_FUNCTION);
+    and_l(~((1<<4)|(1<<24)),&GPIO1_ENABLE);
+}
+
+bool button_hold(void)
+{
+    /* GPIO36 active high */
+    return (GPIO1_READ & (1<<4))?true:false;
+}
+
+
+/*
+ * Get button pressed from hardware
+ */
+int button_read_device(void)
+{
+    int btn = BUTTON_NONE;
+    int data = 0;
+    static bool hold_button = false;
+
+    /* for moving average filter */
+    static unsigned short button_filter[4];
+    static unsigned char index;
+
+    bool hold_button_old;
+
+    /* normal buttons */
+    hold_button_old = hold_button;
+    hold_button = button_hold();
+    
+    
+#ifndef BOOTLOADER
+    if (hold_button != hold_button_old)
+        backlight_hold_changed(hold_button);
+#endif
+
+    if (!hold_button)
+    {
+
+        /* simple moving average filter with 4 item window */
+        button_filter[index&0x03] = adc_scan(ADC_BUTTONS);
+        index++;
+        
+        data = (button_filter[0]+button_filter[1] \
+               +button_filter[2]+button_filter[3])>>2;
+
+
+        if (data < 2250) // valid button
+        {
+	    if (data < 900) /* middle */
+            {
+                if (data < 500)
+                {
+                    if (data > 200)
+                        /* 200 - 500 */
+                        btn = BUTTON_REC;
+                }
+                else /* 900 - 500 */
+                    btn = BUTTON_VOL_DOWN;
+            }
+            else /* 2250 - 900 */
+            {
+                if (data < 1600)
+                {
+                    /* 1600 - 900 */
+                    if (data < 1200)
+                        /* 1200 - 900 */
+                        btn = BUTTON_VOL_UP;
+                    else /* 1600 - 1200 */
+                        btn = BUTTON_NEXT;
+                }
+                else /* 1600 - 2250 */
+                {
+                    if (data < 1900)
+                        /* 1900 - 1600 */
+                        btn = BUTTON_PREV;
+                    else /* 1900 - 2250 */
+                        btn = BUTTON_SELECT;
+                }
+	    }	    
+        }
+    }
+
+
+    data = GPIO1_READ;
+
+    /* GPIO56 active high main PLAY/PAUSE/ON */
+    if (!hold_button && ((data & (1<<24))))
+        btn |= BUTTON_PLAY;
+        
+    return btn;
+}
diff --git a/firmware/target/coldfire/mpio/hd200/lcd-as-hd200.S b/firmware/target/coldfire/mpio/hd200/lcd-as-hd200.S
new file mode 100644
index 0000000..add9f69
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/lcd-as-hd200.S
@@ -0,0 +1,103 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h" 
+#include "cpu.h"
+
+
+#define LCD_BASE_ADDRESS 0xf0000000
+
+    .section    .icode,"ax",@progbits
+
+    .align      2
+    .global     lcd_write_command
+    .type       lcd_write_command,@function
+
+lcd_write_command:
+    move.l  (4, %sp), %d0
+    move.w  %d0, LCD_BASE_ADDRESS	/* data is 1byte but CF uses word
+                                         * transfers only */
+    rts
+.wc_end:
+    .size   lcd_write_command,.wc_end-lcd_write_command
+
+
+    .align      2
+    .global     lcd_write_command_e
+    .type       lcd_write_command_e,@function
+
+lcd_write_command_e:
+    lea.l   LCD_BASE_ADDRESS, %a0
+
+    move.l  (4, %sp), %d0       /* Command */
+    move.w  %d0, (%a0)         
+    move.l  (8, %sp), %d0       /* Data */
+    move.w  %d0, (%a0)          /* Write to LCD */
+
+    rts
+.wce_end:
+    .size   lcd_write_command_e,.wce_end-lcd_write_command_e
+
+
+    .align      2
+    .global     lcd_write_data
+    .type       lcd_write_data,@function
+
+/* PIXELFORMAT = VERTICAL_INTERLEAVED
+ * this means that data is packed verticaly in 8 pixels columns
+ * first byte is lsb of 2bit color in column
+ * second byte is msb of 2bit color in column
+ * so one word of data equals 8 pixels i 2bits color depth packed
+ * verticaly
+ */
+lcd_write_data:
+    movem.l (4, %sp), %a0	     /* Data pointer */
+    move.l  (8, %sp), %d0            /* Length i in words */
+    lea     LCD_BASE_ADDRESS+2, %a1  /* LCD data port address */
+
+    btst    #0, %d0    /* longwords multiply? */
+    beq    .l_write
+
+.w_write:
+    move.w  (%a0)+, %d1  /* load data         3 cycles*/
+    move.w  %d1, (%a1)   /* first byte        1 cycle*/
+    lsr.l   #8, %d1      /* load second byte  1 cycle*/
+    move.w  %d1, (%a1)   /* transfer          1 cycle*/
+    subq.l  #1, %d0      /* decrement counter 1 cycle*/
+    beq     .write_end   
+    
+.l_write:
+    move.l  (%a0)+, %d1  /* load data         2 cycles*/
+    swap    %d1          /*                   1 cycle */
+    move.w  %d1, (%a1)   /* first byte        1 cycle*/
+    lsr.l   #8, %d1      /*                   1 cycle */
+    move.w  %d1, (%a1)   /* second byte       1 cycle*/
+    lsr.l   #8, %d1      /*                   1 cycle */
+    move.w  %d1, (%a1)   /* third byte        1 cycle*/
+    lsr.l   #8, %d1      /*                   1 cycle */
+    move.w  %d1, (%a1)   /* forth byte        1 cycle*/
+    subq.l  #2, %d0      /* decrement counter 1 cycle*/
+    bne     .l_write
+
+.write_end:
+    rts
+    .size   lcd_write_data,.wd_end-lcd_write_data
+
diff --git a/firmware/target/coldfire/mpio/hd200/lcd-hd200.c b/firmware/target/coldfire/mpio/hd200/lcd-hd200.c
new file mode 100644
index 0000000..8cb9e8e
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/lcd-hd200.c
@@ -0,0 +1,241 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+
+#include "system.h"
+#include "kernel.h"
+#include "lcd.h"
+
+/*** definitions ***/
+/* TOMATO LSI 0350 - definitions and slightly tweaked functions
+ * taken from lcd-remote-iaudio.c 
+ */
+
+#define LCD_SET_DUTY_RATIO 0x48
+#define LCD_SELECT_ADC     0xa0
+#define LCD_SELECT_SHL     0xc0
+#define LCD_SET_COM0       0x44
+#define LCD_OSC_ON         0xab
+#define LCD_SELECT_DCDC    0x64
+#define LCD_SELECT_RES     0x20
+#define LCD_SET_VOLUME     0x81
+#define LCD_SET_BIAS       0x50
+#define LCD_CONTROL_POWER  0x28
+#define LCD_DISPLAY_ON     0xae
+#define LCD_SET_INITLINE   0x40
+#define LCD_SET_COLUMN     0x10
+#define LCD_SET_PAGE       0xb0
+#define LCD_SET_GRAY       0x88
+#define LCD_SET_PWM_FRC    0x90
+#define LCD_SET_POWER_SAVE 0xa8
+#define LCD_REVERSE        0xa6
+#define LCD_RESET	   0xe2
+
+/* cached settings */
+static bool cached_invert = false;
+static bool cached_flip = false;
+static int cached_contrast = DEFAULT_CONTRAST_SETTING;
+bool lcd_initialized = false;
+
+/*** hardware configuration ***/
+int lcd_default_contrast(void)
+{
+    return DEFAULT_CONTRAST_SETTING;
+}
+
+void lcd_powersave(bool on)
+{
+/* What is the point of having else construct here? */
+    if(lcd_initialized) {
+        if (on)
+            lcd_write_command(LCD_SET_POWER_SAVE | 1);
+        else
+            lcd_write_command(LCD_SET_POWER_SAVE | 1);
+    }
+}
+
+void lcd_set_contrast(int val)
+{
+    if (val < MIN_CONTRAST_SETTING)
+        val = MIN_CONTRAST_SETTING;
+    else if (val > MAX_CONTRAST_SETTING)
+        val = MAX_CONTRAST_SETTING;
+
+    cached_contrast = val;
+    if(lcd_initialized)
+        lcd_write_command_e(LCD_SET_VOLUME, val);
+}
+
+void lcd_set_invert_display(bool yesno)
+{
+    cached_invert = yesno;
+    if(lcd_initialized)
+        lcd_write_command(LCD_REVERSE | yesno);
+
+}
+
+/* turn the display upside down (call lcd_update() afterwards) */
+void lcd_set_flip(bool yesno)
+{
+    cached_flip = yesno;
+    if(lcd_initialized)
+    {
+        if(yesno)
+        {
+            lcd_write_command(LCD_SELECT_ADC | 1);
+            lcd_write_command(LCD_SELECT_SHL | 0);
+            lcd_write_command_e(LCD_SET_COM0, 0);
+        }
+        else
+        {
+            lcd_write_command(LCD_SELECT_ADC | 0);
+            lcd_write_command(LCD_SELECT_SHL | 8);
+            lcd_write_command_e(LCD_SET_COM0, 0);
+        }
+    }
+
+}
+
+void lcd_shutdown(void)
+{
+    /* Set power save -> Power OFF (VDD - VSS) .. that's it */
+    if (lcd_initialized)
+        lcd_write_command(LCD_SET_POWER_SAVE | 1);
+}
+
+void lcd_init_device(void)
+{
+    and_l(~0x00000800, &GPIO_FUNCTION); /* CS3 line */ 
+
+    /* LCD Reset GPO34 */
+    or_l(0x00000004, &GPIO1_ENABLE);	/* set as output */
+    or_l(0x00000004, &GPIO1_FUNCTION);  /* switch to secondary function - GPIO */
+   
+    and_l(~0x00000004, &GPIO1_OUT);	/* RESET low */
+    sleep(1);				/* delay at least 1000 ns */
+    or_l(0x00000004, &GPIO1_OUT);	/* RESET high */
+    sleep(1);
+
+    /* parameters setup taken from original firmware */
+    lcd_write_command(LCD_RESET);
+    lcd_write_command_e(LCD_SET_DUTY_RATIO,0x80); /* 1/128 */
+    lcd_write_command(LCD_OSC_ON);
+    lcd_write_command(LCD_SELECT_DCDC | 3); /* DC/DC 6xboost */
+    lcd_write_command(LCD_SELECT_RES | 7); /* Regulator resistor: 7.2 */
+    lcd_write_command(LCD_SET_BIAS | 6); /* 1/11 */
+    lcd_write_command(LCD_SET_PWM_FRC | 6); /* 3FRC + 12PWM */
+    lcd_write_command_e(LCD_SET_GRAY | 0, 0x00);
+    lcd_write_command_e(LCD_SET_GRAY | 1, 0x00);
+    lcd_write_command_e(LCD_SET_GRAY | 2, 0x0c);
+    lcd_write_command_e(LCD_SET_GRAY | 3, 0x00);
+    lcd_write_command_e(LCD_SET_GRAY | 4, 0xc4);
+    lcd_write_command_e(LCD_SET_GRAY | 5, 0x00);
+    lcd_write_command_e(LCD_SET_GRAY | 6, 0xcc);
+    lcd_write_command_e(LCD_SET_GRAY | 7, 0x00);
+
+    lcd_write_command(LCD_CONTROL_POWER | 7); /* All circuits ON */
+    lcd_write_command(LCD_DISPLAY_ON | 1); /* display on */
+
+    /* Ok we are ready */
+    lcd_initialized = true;
+
+    lcd_set_flip(cached_flip);
+    lcd_set_contrast(cached_contrast);
+    lcd_set_invert_display(cached_invert);
+
+    lcd_update();
+}
+
+/* Update the display.
+   This must be called after all other LCD functions that change the display. */
+void lcd_update(void) ICODE_ATTR;
+void lcd_update(void)
+{
+   int y;
+    if(!lcd_initialized)
+	return;
+    
+        for(y = 0;y < LCD_FBHEIGHT;y++)
+        {
+            lcd_write_command(LCD_SET_PAGE | y);
+            lcd_write_command_e(LCD_SET_COLUMN, 0);
+            lcd_write_data(lcd_framebuffer[y], LCD_WIDTH);
+        }
+    
+
+}
+
+/* Update a fraction of the display. */
+void lcd_update_rect(int, int, int, int) ICODE_ATTR;
+void lcd_update_rect(int x, int y, int width, int height)
+{
+    int ymax;
+
+    if (!lcd_initialized)
+   	return;
+ 
+
+        /* The Y coordinates have to work on even 8 pixel rows */
+        ymax = (y + height-1) >> 3;
+        y >>= 3;
+
+        if(x + width > LCD_WIDTH)
+            width = LCD_WIDTH - x;
+        if (width <= 0)
+            return; /* nothing left to do, 0 is harmful to lcd_write_data() */
+        if(ymax >= LCD_FBHEIGHT)
+            ymax = LCD_FBHEIGHT-1;
+
+        /* Copy specified rectange bitmap to hardware */
+        for (; y <= ymax; y++)
+        {
+            lcd_write_command(LCD_SET_PAGE | y ); 
+            lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0x0f);
+            lcd_write_data (&lcd_framebuffer[y][x], width);
+        }
+    
+}
+
+void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases,
+                         int x, int by, int width, int bheight, int stride)
+{
+    (void)values;
+    (void)phases;
+    (void)x;
+    (void)by;
+    (void)width;
+    (void)bheight;
+    (void)stride;
+    /* empty stub */
+}
+
+void lcd_blit_mono(const unsigned char *data, int x, int by, int width,
+                   int bheight, int stride)
+{
+    (void)data;
+    (void)x;
+    (void)by;
+    (void)width;
+    (void)bheight;
+    (void)stride;
+    /* empty stub */
+}
diff --git a/firmware/target/coldfire/mpio/hd200/power-hd200.c b/firmware/target/coldfire/mpio/hd200/power-hd200.c
new file mode 100644
index 0000000..dd8576b
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/power-hd200.c
@@ -0,0 +1,113 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "cpu.h"
+#include <stdbool.h>
+#include "kernel.h"
+#include "system.h"
+#include "lcd.h"
+#include "power.h"
+
+#if CONFIG_TUNER
+bool tuner_power(bool status)
+{
+    (void)status;
+    if (status)
+    {
+        and_l(~(1<<17), &GPIO1_OUT);
+    }
+    else
+    {
+        or_l((1<<17), &GPIO1_OUT);
+    }
+
+    return status;
+}
+#endif /* #if CONFIG_TUNER */
+
+void power_init(void)
+{
+    /* GPIO53 has to be high - low resets device */
+    /* GPIO49 is FM related */
+    or_l((1<<21)|(1<<17), &GPIO1_OUT);
+    or_l((1<<21)|(1<<17), &GPIO1_ENABLE);
+    or_l((1<<21)|(1<<17)|(1<<14), &GPIO1_FUNCTION);
+
+    and_l(~(1<<15), &GPIO_OUT);
+    or_l((1<<15),&GPIO_ENABLE);
+    or_l((1<<15),&GPIO_FUNCTION);
+
+    or_l((1<<23), &GPIO_OUT);
+    and_l(~(1<<23), &GPIO_ENABLE);
+    or_l((1<<23), &GPIO_FUNCTION);
+
+#ifndef BOOTLOADER
+    /* The boot loader controls the power */
+    ide_power_enable(true);
+#endif
+}
+
+unsigned int power_input_status(void)
+{
+    unsigned int status = POWER_INPUT_NONE;
+/* GPIO46 is AC plug detect (low = AC plugged) */
+    if (!(GPIO1_READ & (1<<14)))
+            status |= POWER_INPUT_MAIN_CHARGER;
+
+    return status;
+}
+
+/* Returns true if the unit is charging the batteries. */
+bool charging_state(void)
+{
+    if (!(GPIO1_READ & (1<<14)))
+        return (GPIO_READ & (1<<30) )?false:true;
+    else
+        return false;
+}
+
+void ide_power_enable(bool on)
+{
+   (void)on;
+   if (on)
+        and_l(~(1<<31),&GPIO_OUT);
+    else
+        or_l((1<<31),&GPIO_OUT);
+
+    or_l((1<<31),&GPIO_ENABLE);
+    or_l((1<<31),&GPIO_FUNCTION);
+
+}
+
+bool ide_powered(void)
+{
+    return true;
+}
+
+void power_off(void)
+{
+    lcd_shutdown();
+    set_irq_level(DISABLE_INTERRUPTS);
+    and_l(~(1<<21), &GPIO1_OUT); /* pull KEEPACT low */
+    asm("halt");
+    while(1);
+}
diff --git a/firmware/target/coldfire/mpio/hd200/powermgmt-hd200.c b/firmware/target/coldfire/mpio/hd200/powermgmt-hd200.c
new file mode 100644
index 0000000..23a0bac
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/powermgmt-hd200.c
@@ -0,0 +1,59 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "adc.h"
+#include "powermgmt.h"
+
+const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
+{
+    3700
+};
+
+const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
+{
+    3650
+};
+
+/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
+const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
+{
+    /* from OF and measurements voltage range is 3.7-4.1 V */
+    { 3700, 3740, 3780, 3820, 3860, 3900, 3940, 3980, 4020, 4060, 4100 }
+};
+
+/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
+const unsigned short percent_to_volt_charge[11] =
+{
+    /* values measured over one full charging cycle */
+    3540, 3860, 3930, 3980, 4000, 4020, 4040, 4080, 4130, 4180, 4230 /* LiPo */
+};
+
+/* 3.33V as reference */
+#define BATTERY_SCALE_FACTOR 3330
+
+
+/* Returns battery voltage from ADC [millivolts] */
+unsigned int battery_adc_voltage(void)
+{
+    return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 11;
+}
+
diff --git a/firmware/target/coldfire/mpio/hd200/system-hd200.c b/firmware/target/coldfire/mpio/hd200/system-hd200.c
new file mode 100644
index 0000000..06628c0
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/system-hd200.c
@@ -0,0 +1,125 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include "cpu.h"
+#include "kernel.h"
+#include "system.h"
+#include "power.h"
+#include "timer.h"
+
+/* Settings for all possible clock frequencies (with properly working timers)
+ *
+ *                    xxx_REFRESH_TIMER below
+ * system.h, CPUFREQ_xxx_MULT    |
+ *              |                |
+ *              V                V
+ *                   PLLCR &   Rftim.                 IDECONFIG1/IDECONFIG2
+ * CPUCLK/Hz  MULT ~0x70c00000  16MB  CSCR0   CSCR1   CS2Pre CS2Post CS2Wait
+ * -------------------------------------------------------------------------
+ *  11289600    1   0x00000200    4   0x0180  0x0180     1      1       0
+ *  22579200    2   0x05028049   10   0x0180  0x0180     1      1       0
+ *  33868800    3   0x03024049   15   0x0180  0x0180     1      1       0
+ *  45158400    4   0x05028045   21   0x0180  0x0180     1      1       0
+ *  56448000    5   0x02028049   26   0x0580  0x0580     2      1       0
+ *  67737600    6   0x03024045   32   0x0580  0x0980     2      1       0
+ *  79027200    7   0x0302a045   37   0x0580  0x0d80     2      1       0
+ *  90316800    8   0x03030045   43   0x0980  0x0d80     2      1       0
+ * 101606400    9   0x01024049   48   0x0980  0x1180     2      1       0
+ * 112896000   10   0x01028049   54   0x0980  0x1580     3      1       0
+ * 124185600   11   0x0102c049   59   0x0980  0x1180     3      1       1
+ */
+
+#define MAX_REFRESH_TIMER     59
+#define NORMAL_REFRESH_TIMER  21
+#define DEFAULT_REFRESH_TIMER 4
+
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+void set_cpu_frequency (long) __attribute__ ((section (".icode")));
+void set_cpu_frequency(long frequency)
+#else
+void cf_set_cpu_frequency (long) __attribute__ ((section (".icode")));
+void cf_set_cpu_frequency(long frequency)
+#endif    
+{
+    switch(frequency)
+    {
+    case CPUFREQ_MAX:
+        DCR = (0x8200 | DEFAULT_REFRESH_TIMER);
+              /* Refresh timer for bypass frequency */
+        PLLCR &= ~1;  /* Bypass mode */
+        timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
+        PLLCR = 0x0102c049 | (PLLCR & 0x70C00000);
+        CSCR0 = 0x00001180; /* Flash: 4 wait states */
+        CSCR3 = 0x00001180; /* LCD: 4 wait states */
+        while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
+                                            This may take up to 10ms! */
+        timers_adjust_prescale(CPUFREQ_MAX_MULT, true);
+        DCR = (0x8200 | MAX_REFRESH_TIMER);          /* Refresh timer */
+        cpu_frequency = CPUFREQ_MAX;
+        IDECONFIG1 = (1<<28)|(1<<20)|(1<<18)|(1<<13)|(3<<10);
+                    /* BUFEN2 enable on /CS2 | CS2Post 1 clock| CS2Pre 3 clocks*/
+        IDECONFIG2 = (1<<18)|(1<<16)|(1<<8)|(1<<0); /* TA /CS2 enable + CS2wait */
+
+	and_l(~(0x07<<16), &ADCONFIG);
+	or_l(((1<<7)|(1<<2)|(1<<0))<<16, &ADCONFIG); /* adclk = busclk/32 */
+
+        break;
+
+    case CPUFREQ_NORMAL:
+        DCR = (DCR & ~0x01ff) | DEFAULT_REFRESH_TIMER;
+              /* Refresh timer for bypass frequency */
+        PLLCR &= ~1;  /* Bypass mode */
+        timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
+        PLLCR = 0x05028045 | (PLLCR & 0x70C00000);
+        CSCR0 = 0x00000580; /* Flash: 1 wait state */
+        CSCR3 = 0x00000980; /* LCD: 0 wait states */
+        while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
+                                            This may take up to 10ms! */
+        timers_adjust_prescale(CPUFREQ_NORMAL_MULT, true);
+        DCR = (0x8000 | NORMAL_REFRESH_TIMER);       /* Refresh timer */
+        cpu_frequency = CPUFREQ_NORMAL;
+	IDECONFIG1 = (1<<28)|(1<<20)|(1<<18)|(1<<13)|(1<<10);
+	IDECONFIG2 = (1<<18)|(1<<16);
+
+	and_l(~(0x07<<16), &ADCONFIG);
+	or_l(((1<<7)|(1<<1)|(1<<0))<<16, &ADCONFIG); /* adclk = busclk/8 */
+
+        break;
+    default:
+        DCR = (DCR & ~0x01ff) | DEFAULT_REFRESH_TIMER;
+              /* Refresh timer for bypass frequency */
+        PLLCR &= ~1;  /* Bypass mode */
+        timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true);
+        /* Power down PLL, but keep CLSEL and CRSEL */
+        PLLCR = 0x00000200 | (PLLCR & 0x70C00000);
+        CSCR0 = 0x00000180; /* Flash: 0 wait states */
+        CSCR3 = 0x00000980; /* LCD: 0 wait states */
+        DCR = (0x8000 | DEFAULT_REFRESH_TIMER);       /* Refresh timer */
+        cpu_frequency = CPUFREQ_DEFAULT;
+	IDECONFIG1 = (1<<28)|(1<<20)|(1<<18)|(1<<13)|(1<<10);
+	IDECONFIG2 = (1<<18)|(1<<16);
+
+	and_l(~(0x07<<16), &ADCONFIG);
+	or_l(((1<<7)|(1<<0))<<16, &ADCONFIG); /* adclk = busclk/2 */
+
+        break;
+    }
+}
diff --git a/firmware/target/coldfire/mpio/hd200/usb-hd200.c b/firmware/target/coldfire/mpio/hd200/usb-hd200.c
new file mode 100644
index 0000000..8f348b8
--- /dev/null
+++ b/firmware/target/coldfire/mpio/hd200/usb-hd200.c
@@ -0,0 +1,81 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include <stdbool.h>
+#include "cpu.h"
+#include "system.h"
+#include "kernel.h"
+#include "usb.h"
+
+void usb_init_device(void)
+{
+    /* GPIO42 is USB detect input
+     * but it also serves as MCLK2 for DAC
+     */
+    and_l(~(1<<4), &GPIO1_OUT);
+    or_l((1<<4)|(1<<18), &GPIO1_ENABLE);   /* GPIO36 GPIO50 */
+    or_l((1<<4)|(1<<18), &GPIO1_FUNCTION); 
+
+     /* GPIO22 GPIO30*/
+     /* GPIO31 has to be low to ATA work */
+    or_l((1<<22)|(1<<30), &GPIO_OUT);
+    or_l((1<<22)|(1<<30)|(1<<31), &GPIO_ENABLE);
+    or_l((1<<22)|(1<<30)|(1<<31), &GPIO_FUNCTION);
+}
+
+int usb_detect(void)
+{
+    /* GPIO42 active low*/
+    return (GPIO1_READ & (1<<10)) ? USB_EXTRACTED : USB_INSERTED;
+}
+
+void usb_enable(bool on)
+{
+   
+    if(on)
+    {
+        or_l((1<<18),&GPIO1_OUT); /* GPIO50 high */
+
+        and_l(~(1<<30),&GPIO_OUT);  /* GPIO30 low */
+        /* GPIO36 low delay GPIO36 high delay */
+        and_l(~(1<<4),&GPIO1_OUT);
+        or_l((1<<4),&GPIO1_OUT);
+
+        and_l(~(1<<18),&GPIO1_OUT); /* GPIO50 low */
+        sleep(HZ/5); /* delay 200 ms */
+        and_l(~(1<<22),&GPIO_OUT); /* GPIO22 low */
+    }
+    else
+    {
+        /* GPIO36 low delay GPIO36 high delay */
+        and_l(~(1<<4),&GPIO1_OUT);
+        sleep(HZ/100);
+        or_l((1<<4),&GPIO1_OUT);
+        sleep(HZ/100);
+
+        or_l((1<<22),&GPIO_OUT);  /* GPIO22 high */
+        or_l((1<<30),&GPIO_OUT);  /* GPIO30 high */
+
+        and_l(~(1<<4),&GPIO1_OUT); /* GPIO36 low */
+
+       //or_l((1<<18),&GPIO1_OUT);  /* GPIO50 high */
+    }
+}
diff --git a/firmware/target/coldfire/wmcodec-coldfire.c b/firmware/target/coldfire/wmcodec-coldfire.c
new file mode 100644
index 0000000..4403b9a
--- /dev/null
+++ b/firmware/target/coldfire/wmcodec-coldfire.c
@@ -0,0 +1,52 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Coldfire specific code for Wolfson audio codecs based on
+ * wmcodec-pp.c
+ *
+ * Based on code from the ipodlinux project - http://ipodlinux.org/
+ * Adapted for Rockbox in December 2005
+ *
+ * Original file: linux/arch/armnommu/mach-ipod/audio.c
+ *
+ * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "system.h"
+#include "audiohw.h"
+#include "i2c-coldfire.h"
+#include "i2s.h"
+#include "wmcodec.h"
+
+#if defined(MPIO_HD200)
+#define I2C_CODEC_ADDRESS 0x34
+#define I2C_IFACE I2C_IFACE_1
+#endif
+
+void audiohw_init(void)
+{
+    audiohw_preinit();
+}
+
+void wmcodec_write(int reg, int data)
+{
+    unsigned char wmdata[2];
+    wmdata[0] = (reg << 1) | ((data & 0x100)>>8);
+    wmdata[1] = data & 0xff;
+    i2c_write(I2C_IFACE,I2C_CODEC_ADDRESS,wmdata,2);
+    return;
+}
diff --git a/rbutil/mkmpioboot/Makefile b/rbutil/mkmpioboot/Makefile
new file mode 100644
index 0000000..f503927
--- /dev/null
+++ b/rbutil/mkmpioboot/Makefile
@@ -0,0 +1,94 @@
+
+#change for releases
+ifndef APPVERSION
+APPVERSION=`../../tools/version.sh ../../`
+endif
+
+# We use the UCL code available in the Rockbox tools/ directory
+CFLAGS=-I../../tools/ucl/include -Wall -DVERSION=\"$(APPVERSION)\"
+
+ifndef V
+SILENT = @
+endif
+
+ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN)
+OUTPUT=mkmpioboot.exe
+CFLAGS+=-mno-cygwin
+else
+ifeq ($(findstring MINGW,$(shell uname)),MINGW)
+OUTPUT=mkmpioboot.exe
+else
+ifeq ($(findstring mingw,$(CC)),mingw)
+OUTPUT=mkmpioboot.exe
+else
+OUTPUT=mkmpioboot
+endif
+endif
+endif
+
+ifdef RBARCH
+CFLAGS += -arch $(RBARCH)
+OBJDIR = $(RBARCH)/
+endif
+
+
+all: $(OUTPUT)
+
+# inputs
+LIBSOURCES := mkmpioboot.c
+SOURCES := $(LIBSOURCES) main.c
+OBJS := $(patsubst %.c,%.o,$(addprefix $(OBJDIR),$(SOURCES)))
+LIBOBJS := $(patsubst %.c,%.o,$(addprefix $(OBJDIR),$(LIBSOURCES)))
+EXTRADEPS := $(LIBUCL)
+
+# explicit dependencies
+$(OBJDIR)mkmpioboot.o: mkmpioboot.c mkmpioboot.h
+$(OBJDIR)main.o: main.c
+
+$(OBJDIR)%.o: %.c
+	@echo CC $< $
+	$(SILENT)mkdir -p $(dir $@)
+	$(SILENT)$(CC) $(CFLAGS) -c -o $@ $<
+
+libmkamsboot$(RBARCH).a: $(LIBOBJS)
+	@echo AR $@
+	$(SILENT)$(AR) ruc $(TARGET_DIR)$@ $^
+
+# building the standalone executable
+$(OUTPUT): $(OBJS) $(EXTRADEPS)
+	@echo LD $@
+	$(SILENT)$(CC) $(CFLAGS) -o $(OUTPUT) $(OBJS) $(EXTRADEPS)
+
+# some trickery to build ppc and i386 from a single call
+ifeq ($(RBARCH),)
+$(TARGET_DIR)libmkmpiobooti386.a:
+	make RBARCH=i386 TARGET_DIR=$(TARGET_DIR) libmkmpiobooti386.a
+
+$(TARGET_DIR)libmkmpiobootppc.a:
+	make RBARCH=ppc TARGET_DIR=$(TARGET_DIR) libmkmpiobootppc.a
+endif    
+
+libmkmpioboot-universal: $(TARGET_DIR)libmkmpiobooti386.a $(TARGET_DIR)libmkmpiobootppc.a
+	@echo lipo $(TARGET_DIR)libmkmpioboot.a
+	$(SILENT) rm -f $(TARGET_DIR)libmkmpioboot.a
+	$(SILENT)lipo -create $(TARGET_DIR)libmkmpiobootppc.a $(TARGET_DIR)libmkmpiobooti386.a -output $(TARGET_DIR)libmkmpioboot.a
+
+clean:
+	rm -f $(OBJS) $(OUTPUT) libmkmpioboot.o $(TARGET_DIR)libmkmpioboot*.a mkmpioboot.dmg
+	rm -rf mkmpioboot-* i386 ppc $(OBJDIR)
+
+mkmpioboot-i386:
+	$(MAKE) RBARCH=i386
+	mv mkmpioboot mkmpioboot-i386
+
+mkmpioboot-ppc:
+	$(MAKE) RBARCH=ppc
+	mv mkmpioboot mkmpioboot-ppc
+
+mkmpioboot-mac: mkmpioboot-i386 mkmpioboot-ppc
+	$(SILENT)lipo -create mkmpioboot-ppc mkmpioboot-i386 -output mkmpioboot-mac
+
+mkmpioboot.dmg: mkmpioboot-mac
+	mkdir -p mkmpioboot-dmg
+	cp -p mkmpioboot-mac mkmpioboot-dmg
+	hdiutil create -srcfolder mkmpioboot-dmg mkmpioboot.dmg
diff --git a/rbutil/mkmpioboot/main.c b/rbutil/mkmpioboot/main.c
new file mode 100644
index 0000000..38e6d25
--- /dev/null
+++ b/rbutil/mkmpioboot/main.c
@@ -0,0 +1,49 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 by Marcin Bukat
+ *
+ * code taken mostly from mkboot.c
+ * Copyright (C) 2005 by Linus Nielsen Feltzing
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "mkmpioboot.h"
+
+static void usage(void)
+{
+    printf("usage: mkmpioboot <firmware file> <boot file> <output file>\n");
+    exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+    char *infile, *bootfile, *outfile;
+    int origin = 0xe0000;   /* MPIO HD200 bootloader address */
+
+    if(argc < 3) {
+        usage();
+    }
+
+        infile = argv[1];
+        bootfile = argv[2];
+        outfile = argv[3];
+
+    return mkmpioboot(infile, bootfile, outfile, origin);
+}
diff --git a/rbutil/mkmpioboot/mkmpioboot.c b/rbutil/mkmpioboot/mkmpioboot.c
new file mode 100644
index 0000000..6d52e53
--- /dev/null
+++ b/rbutil/mkmpioboot/mkmpioboot.c
@@ -0,0 +1,188 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 by Marcin Bukat
+ *
+ * code taken mostly from mkboot.c 
+ * Copyright (C) 2005 by Linus Nielsen Feltzing
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mkmpioboot.h"
+
+#define OF_FIRMWARE_LEN 0x100000 /* size of HD200_UPG.SYS file */
+#define MPIO_STRING_OFFSET 0xfffe0
+
+/* We support only 1.30.05 version of OF for now */
+static char *mpio_string = "HD200  HDD Audio Ver113005";
+
+/* MPIO HD200 firmware is plain binary image
+ * 4 bytes of initial SP (loaded on reset)
+ * 4 bytes of initial PC (loaded on reset)
+ * binary image with entry point 0x00000008
+ *
+ * We put our bootloader code at 0x000e0000
+ * and patch reset vector to jump directly
+ * into our code on reset
+ */
+
+static unsigned char image[OF_FIRMWARE_LEN];
+
+static unsigned int get_uint32be(unsigned char* p)
+{
+    return ((p[0] << 24) | (p[1] << 16) | (p[2]<<8) | p[3]);
+}
+
+static long checksum(unsigned char* buf, unsigned long length)
+{
+    unsigned long chksum = 69; /* MPIO HD200 model number */
+    unsigned long i;
+    
+    if(buf == NULL)
+        return -1;
+
+    for (i = 0; i < length; i++)
+    {
+        chksum += *buf++;
+    }
+
+return chksum;
+}
+
+int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin)
+{
+    FILE *f;
+    int i;
+    int len;
+    unsigned long file_checksum;
+    unsigned char header_checksum[4];
+
+    memset(image, 0xff, sizeof(image));
+
+    /* First, read the mpio original firmware into the image */
+    f = fopen(infile, "rb");
+    if(!f) {
+        perror(infile);
+        return -1;
+    }
+
+    i = fread(image, 1, OF_FIRMWARE_LEN, f);
+    if(i < OF_FIRMWARE_LEN) {
+        perror(infile);
+        fclose(f);
+        return -2;
+    }
+
+    fclose(f);
+
+    /* Now check if we have OF file loaded based on presence
+     * of the version string in firmware 
+     */
+
+    if (strcmp((char*)(image + MPIO_STRING_OFFSET),mpio_string) != 0)
+    {
+        perror("Loaded firmware file does not look like MPIO OF file!");
+        return -3;
+    }
+
+    /* Now, read the boot loader into the image */
+    f = fopen(bootfile, "rb");
+    if(!f) {
+        perror(bootfile);
+        fclose(f);
+        return -4;
+    }
+
+    /* get bootloader size
+     * excluding header
+     */
+    fseek(f, 0, SEEK_END);
+    len = ftell(f) - 8;
+
+    /* Now check if the place we want to put
+     * our bootloader is free
+     */
+    for(i=0;i<len;i++)
+    {
+        if (image[origin+i] != 0)
+        {
+            perror("Place for bootloader in OF file not empty");
+            return -5;
+        }
+    }
+
+    fseek(f, 0, SEEK_SET);
+
+    /* get bootloader checksum from the header*/
+    fread(header_checksum,1,4,f);
+
+    /* omit header */
+    fseek(f, 8, SEEK_SET);
+
+    i = fread(image + origin, 1, len, f);
+    if(i < len) {
+        perror(bootfile);
+        fclose(f);
+        return -6;
+    }
+
+    fclose(f);
+
+    /* calculate checksum and compare with data
+     * from header
+     */
+    file_checksum = checksum(image + origin, len);
+
+    if ( file_checksum != get_uint32be(header_checksum) )
+    {
+        printf("Bootloader checksum error\n");
+        return -7;
+    }
+
+    f = fopen(outfile, "wb");
+    if(!f) {
+        perror(outfile);
+        return -8;
+    }
+
+    /* Patch the stack pointer address */    
+    image[0] = image[origin + 0];
+    image[1] = image[origin + 1];
+    image[2] = image[origin + 2];
+    image[3] = image[origin + 3];
+
+    /* Patch the reset vector to start the boot loader */
+    image[4] = image[origin + 4];
+    image[5] = image[origin + 5];
+    image[6] = image[origin + 6];
+    image[7] = image[origin + 7];
+
+    i = fwrite(image, 1, OF_FIRMWARE_LEN, f);
+    if(i < OF_FIRMWARE_LEN) {
+        perror(outfile);
+        fclose(f);
+        return -9;
+    }
+
+    printf("Wrote 0x%x bytes in %s\n", OF_FIRMWARE_LEN, outfile);
+    
+    fclose(f);
+    
+    return 0;
+}
diff --git a/rbutil/mkmpioboot/mkmpioboot.h b/rbutil/mkmpioboot/mkmpioboot.h
new file mode 100644
index 0000000..794f9df
--- /dev/null
+++ b/rbutil/mkmpioboot/mkmpioboot.h
@@ -0,0 +1,37 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 by Marcin Bukat
+ * code based mainly on mkboot.h
+ * Copyright (C) 2008 by Dominik Riebeling
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef MKMPIOBOOT_H
+#define MKMPIOBOOT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+