New port: iPod Nano 3G

Currently, only a bootloader can be built successfully. The development bootloader is functional, it enables further progress on the port.

This is a part of the large iPod Nano 3G and iPod Nano 4G support patch.

Credit: Cástor Muñoz <cmvidal@gmail.com>
Change-Id: Idf85e42334b0e0ae36f9ed273e2940d5d7736e34
This commit is contained in:
Vencislav Atanasov 2024-12-16 16:24:30 +02:00 committed by Solomon Peachy
parent 96615af033
commit d6cd237f80
24 changed files with 2458 additions and 68 deletions

View file

@ -0,0 +1,46 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: adc-s5l8700.c 21775 2009-07-11 14:12:02Z bertrik $
*
* Copyright (C) 2009 by Bertrik Sikken
*
* 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 "inttypes.h"
#include "s5l87xx.h"
#include "adc.h"
#include "adc-target.h"
#include "pmu-target.h"
#include "kernel.h"
/* Returns battery voltage [millivolts] */
unsigned int adc_read_battery_voltage(void)
{
return 0;
}
/* API functions */
unsigned short adc_read(int channel)
{
(void) channel;
return 0;
}
void adc_init(void)
{
}

View file

@ -0,0 +1,43 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: adc-target.h 21734 2009-07-09 20:17:47Z bertrik $
*
* Copyright (C) 2006 by Barry Wardell
*
* 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_
#include <stdbool.h>
#include "config.h"
enum
{
ADC_BATTERY = 0,
ADC_USBDATA,
ADC_ACCESSORY,
NUM_ADC_CHANNELS
};
#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
unsigned short adc_read_millivolts(int channel);
unsigned int adc_read_battery_voltage(void);
unsigned int adc_read_usbdata_voltage(bool dp);
int adc_read_accessory_resistor(void);
const char *adc_name(int channel);
#endif

View file

@ -0,0 +1,77 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: audio-nano2g.c 23095 2009-10-11 09:17:12Z dave $
*
* Copyright (C) 2006 by Michael Sevakis
*
* 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"
#if INPUT_SRC_CAPS != 0
void audio_set_output_source(int source)
{
if ((unsigned)source >= AUDIO_NUM_SOURCES)
source = AUDIO_SRC_PLAYBACK;
} /* audio_set_output_source */
void audio_input_mux(int source, unsigned flags)
{
(void)flags;
/* Prevent pops from unneeded switching */
static int last_source = AUDIO_SRC_PLAYBACK;
switch (source)
{
default: /* playback - no recording */
source = AUDIO_SRC_PLAYBACK;
case AUDIO_SRC_PLAYBACK:
#ifdef HAVE_RECORDING
if (source != last_source)
{
audiohw_set_monitor(false);
audiohw_disable_recording();
}
#endif
break;
#ifdef HAVE_MIC_REC
case AUDIO_SRC_MIC: /* recording only */
if (source != last_source)
{
audiohw_set_monitor(false);
audiohw_enable_recording(true); /* source mic */
}
break;
#endif
#ifdef HAVE_LINE_REC
case AUDIO_SRC_LINEIN: /* recording only */
if (source != last_source)
{
audiohw_set_monitor(false);
audiohw_enable_recording(false); /* source line */
}
break;
#endif
} /* end switch */
last_source = source;
} /* audio_input_mux */
#endif /* INPUT_SRC_CAPS != 0 */

View file

@ -0,0 +1,68 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: backlight-nano2g.c 28601 2010-11-14 20:39:18Z theseven $
*
* Copyright (C) 2009 by Dave Chapman
*
* 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 <stdbool.h>
#include "config.h"
#include "kernel.h"
#include "backlight.h"
#include "backlight-target.h"
#include "pmu-target.h"
#ifdef HAVE_LCD_SLEEP
#include "lcd.h"
#include "lcd-s5l8702.h"
#endif
// TODO: test
void backlight_hw_brightness(int brightness)
{
pmu_write(D1671_REG_LEDCTL,
(pmu_read(D1671_REG_LEDCTL) & ~D1671_LEDCTL_OUT_MASK) | (brightness>>1));
}
void backlight_hw_on(void)
{
#ifdef HAVE_LCD_SLEEP
if (!lcd_active())
lcd_awake();
#endif
pmu_write(D1671_REG_LEDCTL,
(pmu_read(D1671_REG_LEDCTL) | D1671_LEDCTL_ENABLE));
}
void backlight_hw_off(void)
{
pmu_write(D1671_REG_LEDCTL,
(pmu_read(D1671_REG_LEDCTL) & ~D1671_LEDCTL_ENABLE));
}
bool backlight_hw_init(void)
{
backlight_hw_brightness(DEFAULT_BRIGHTNESS_SETTING);
backlight_hw_on();
return true;
}
/* Kill the backlight, instantly. */
void backlight_hw_kill(void)
{
backlight_hw_off();
}

View file

@ -0,0 +1,31 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: backlight-target.h 21478 2009-06-23 18:11:03Z bertrik $
*
* Copyright (C) 2008 by Marcoen Hirschberg
*
* 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_hw_init(void);
void backlight_hw_on(void);
void backlight_hw_off(void);
void backlight_hw_brightness(int brightness);
void backlight_hw_kill(void);
#endif

View file

@ -0,0 +1,76 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: button-target.h 21828 2009-07-12 22:16:51Z dave $
*
* Copyright (C) 2006 by Barry Wardell
*
* 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 "config.h"
#define HAS_BUTTON_HOLD
void ipod_mini_button_int(void);
void ipod_3g_button_int(void);
void ipod_4g_button_int(void);
/* iPod specific button codes */
#define BUTTON_SELECT 0x00000001
#define BUTTON_MENU 0x00000002
#define BUTTON_LEFT 0x00000004
#define BUTTON_RIGHT 0x00000008
#define BUTTON_SCROLL_FWD 0x00000010
#define BUTTON_SCROLL_BACK 0x00000020
#define BUTTON_PLAY 0x00000040
#define BUTTON_MAIN (BUTTON_SELECT|BUTTON_MENU\
|BUTTON_LEFT|BUTTON_RIGHT|BUTTON_SCROLL_FWD\
|BUTTON_SCROLL_BACK|BUTTON_PLAY)
/* Remote control's buttons */
#ifdef IPOD_ACCESSORY_PROTOCOL
#define BUTTON_RC_DOWN 0x01000000
#define BUTTON_RC_UP 0x00800000
#define BUTTON_RC_SELECT 0x00400000
#define BUTTON_RC_MENU 0x00200000
#define BUTTON_RC_PLAY 0x00100000
#define BUTTON_RC_STOP 0x00080000
#define BUTTON_RC_LEFT 0x00040000
#define BUTTON_RC_RIGHT 0x00020000
#define BUTTON_RC_VOL_UP 0x00010000
#define BUTTON_RC_VOL_DOWN 0x00008000
#define BUTTON_REMOTE (BUTTON_RC_UP|BUTTON_RC_DOWN \
|BUTTON_RC_SELECT|BUTTON_RC_PLAY \
|BUTTON_RC_PLAY|BUTTON_RC_STOP \
|BUTTON_RC_LEFT|BUTTON_RC_RIGHT\
|BUTTON_RC_VOL_UP|BUTTON_RC_VOL_DOWN)
#endif
/* This is for later
#define BUTTON_SCROLL_TOUCH 0x00000200
*/
#define POWEROFF_BUTTON BUTTON_PLAY
#define POWEROFF_COUNT 40
#endif /* _BUTTON_TARGET_H_ */

View file

@ -0,0 +1,68 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: wmcodec-s5l8700.c 22025 2009-07-25 00:49:13Z dave $
*
* S5L8702-specific code for Cirrus codecs
*
* Copyright (c) 2010 Michael Sparmann
*
* 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-s5l8702.h"
#include "s5l87xx.h"
#include "cscodec.h"
void audiohw_init(void)
{
#ifdef HAVE_CS42L55
audiohw_preinit();
#endif
}
unsigned char cscodec_read(int reg)
{
// TODO: not tested
unsigned char data;
i2c_read(0, 0x94, reg, 1, &data);
return data;
}
void cscodec_write(int reg, unsigned char data)
{
// XXX: not tested
i2c_write(0, 0x94, reg, 1, &data);
}
void cscodec_power(bool state)
{
(void)state; //TODO: Figure out which LDO this is
}
void cscodec_reset(bool state)
{
// XXX: not tested
if (state) PDAT(3) &= ~8;
else PDAT(3) |= 8;
}
void cscodec_clock(bool state)
{
// XXX: not tested
if (state) CLKCON3 &= ~0xffff;
else CLKCON3 |= 0x8000;
}

View file

@ -0,0 +1,419 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:
*
* Copyright (C) 2017 Cástor Muñoz
*
* 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 <stdint.h>
#include "config.h"
#include "lcd-s5l8702.h"
#ifdef BOOTLOADER
#include "piezo.h"
#endif
// XXX: For nano3g displays see ili9327, which says it supports 8-bit MIDI interface command and 8-bit param
/* Supported LCD types */
enum {
LCD_TYPE_UNKNOWN = -1,
LCD_TYPE_38B3 = 0,
LCD_TYPE_38C4,
LCD_TYPE_38D5,
LCD_TYPE_38E6,
LCD_TYPE_58XX,
N_LCD_TYPES
};
#if defined(HAVE_LCD_SLEEP) || defined(HAVE_LCD_SHUTDOWN)
/* sleep sequences */
/* 0xb3, 0xe6 */
static const uint8_t lcd_sleep_seq_03[] =
{
CMD, 0x28, 0, /* Display Off */
CMD, 0x10, 0, /* Sleep In */
SLEEP, 5, /* 50 ms */
END
};
/* 0xc4 */
static const uint8_t lcd_sleep_seq_1[] =
{
CMD, 0x28, 0, /* Display Off */
CMD, 0x10, 0, /* Sleep In */
SLEEP, 12, /* 120 ms */
END
};
/* 0xd5 */
static const uint8_t lcd_sleep_seq_2[] =
{
CMD, 0x28, 0, /* Display Off */
CMD, 0x10, 0, /* Sleep In */
END
};
/* 0x58 */
static const uint8_t lcd_sleep_seq_4[] =
{
CMD, 0x10, 0, /* Sleep In */
END
};
// static const void* seq_sleep_by_type[] =
static void* seq_sleep_by_type[] =
{
[LCD_TYPE_38B3] = (void*) lcd_sleep_seq_03,
[LCD_TYPE_38C4] = (void*) lcd_sleep_seq_1,
[LCD_TYPE_38D5] = (void*) lcd_sleep_seq_2,
[LCD_TYPE_38E6] = (void*) lcd_sleep_seq_03,
[LCD_TYPE_58XX] = (void*) lcd_sleep_seq_4,
};
#endif /* HAVE_LCD_SLEEP || HAVE_LCD_SHUTDOWN */
#if defined(HAVE_LCD_SLEEP)
/* awake sequences */
/* 0xb3, 0xc4, 0xd5, 0xd6, 0x58 */
static const uint8_t lcd_awake_seq_01234[] =
{
CMD, 0x11, 0, /* Sleep Out */
SLEEP, 12, /* 120 ms */
CMD, 0x29, 0, /* Display On */
SLEEP, 1, /* 10 ms */
END
};
static void* seq_awake_by_type[] =
{
[LCD_TYPE_38B3] = (void*) lcd_awake_seq_01234,
[LCD_TYPE_38C4] = (void*) lcd_awake_seq_01234,
[LCD_TYPE_38D5] = (void*) lcd_awake_seq_01234,
[LCD_TYPE_38E6] = (void*) lcd_awake_seq_01234,
[LCD_TYPE_58XX] = (void*) lcd_awake_seq_01234,
};
#endif /* HAVE_LCD_SLEEP */
#if defined(BOOTLOADER)
/* init sequences */
// TODO: put something else at the end of the init sequence???, the bootloader without a sleep is very tight ()
/* 0xb3 */
static const uint8_t lcd_init_seq_0[] =
{
CMD, 0xef, 1, 0x80,
/* Power control */
CMD, 0xc0, 1, 0x06,
CMD, 0xc1, 1, 0x03,
CMD, 0xc2, 2, 0x12, 0x00,
CMD, 0xc3, 2, 0x12, 0x00,
CMD, 0xc4, 2, 0x12, 0x00,
CMD, 0xc5, 2, 0x40, 0x38,
/* Display control */
CMD, 0xb1, 2, 0x5f, 0x3f,
CMD, 0xb2, 2, 0x5f, 0x3f,
CMD, 0xb3, 2, 0x5f, 0x3f,
CMD, 0xb4, 1, 0x02,
CMD, 0xb6, 2, 0x12, 0x02,
CMD, 0x35, 1, 0x00, /* Tearing Effect Line On */
CMD, 0x26, 1, 0x10, /* Gamma Set */
CMD, 0xfe, 1, 0x00,
/* Gamma settings */
CMD, 0xe0, 11, 0x0f, 0x70, 0x47, 0x03, 0x02, 0x02, 0xa0, 0x94,
0x05, 0x00, 0x0e,
CMD, 0xe1, 11, 0x02, 0x43, 0x77, 0x00, 0x0f, 0x05, 0x49, 0x0a,
0x02, 0x0e, 0x00,
CMD, 0xe2, 11, 0x2f, 0x63, 0x20, 0x50, 0x00, 0x07, 0xd1, 0x13,
0x00, 0x00, 0x0e,
CMD, 0xe3, 11, 0x50, 0x20, 0x60, 0x23, 0x0f, 0x00, 0x31, 0x1d,
0x07, 0x0e, 0x00,
CMD, 0xe4, 11, 0x5e, 0x50, 0x65, 0x27, 0x00, 0x0b, 0xdf, 0xf1,
0x01, 0x00, 0x0e,
CMD, 0xe5, 11, 0x20, 0x67, 0x55, 0x50, 0x0e, 0x01, 0x1f, 0xfd,
0x0b, 0x0e, 0x00,
CMD, 0x3a, 1, 0x06, /* Pixel Format Set */
CMD, 0x36, 1, 0x60, /* Memory Access Control */
CMD, 0x13, 0, /* Normal Mode On */
/* Awake sequence */
CMD, 0x11, 0, /* Sleep Out */
SLEEP, 12, /* 120 ms */
CMD, 0x29, 0, /* Display On */
SLEEP, 1, /* 10 ms */
END
};
/* 0xc4 */
static const uint8_t lcd_init_seq_1[] =
{
CMD, 0x01, 0, /* Software Reset */
SLEEP, 1, /* 10 ms */
/* Power control */
CMD, 0xc0, 1, 0x01,
CMD, 0xc1, 1, 0x03,
CMD, 0xc2, 2, 0x74, 0x00,
CMD, 0xc3, 2, 0x72, 0x03,
CMD, 0xc4, 2, 0x73, 0x03,
CMD, 0xc5, 2, 0x3c, 0x3c,
/* Display control */
CMD, 0xb1, 2, 0x6a, 0x15,
CMD, 0xb2, 2, 0x6a, 0x15,
CMD, 0xb3, 2, 0x6a, 0x15,
CMD, 0xb4, 1, 0x02,
CMD, 0xb6, 2, 0x12, 0x02,
CMD, 0x35, 1, 0x00, /* Tearing Effect Line On */
CMD, 0x26, 1, 0x10, /* Gamma Set */
/* Gamma settings */
CMD, 0xe0, 11, 0x1e, 0x22, 0x44, 0x00, 0x09, 0x01, 0x47, 0xc1,
0x05, 0x02, 0x09,
CMD, 0xe1, 11, 0x0f, 0x32, 0x35, 0x00, 0x03, 0x05, 0x5e, 0x78,
0x03, 0x00, 0x03,
CMD, 0xe2, 11, 0x0d, 0x74, 0x47, 0x41, 0x07, 0x01, 0x74, 0x41,
0x09, 0x03, 0x07,
CMD, 0xe3, 11, 0x5f, 0x41, 0x27, 0x02, 0x00, 0x03, 0x43, 0x55,
0x02, 0x00, 0x03,
CMD, 0xe4, 11, 0x1b, 0x53, 0x44, 0x51, 0x0b, 0x01, 0x64, 0x20,
0x05, 0x02, 0x09,
CMD, 0xe5, 11, 0x7f, 0x41, 0x26, 0x02, 0x04, 0x00, 0x33, 0x35,
0x01, 0x00, 0x02,
CMD, 0x3a, 1, 0x66, /* Pixel Format Set */
CMD, 0x36, 1, 0x60, /* Memory Access Control */
/* Awake sequence */
CMD, 0x11, 0, /* Sleep Out */
SLEEP, 12, /* 120 ms */
CMD, 0x29, 0, /* Display On */
SLEEP, 1, /* 10 ms */
END
};
/* 0xd5 */
static const uint8_t lcd_init_seq_2[] =
{
CMD, 0xfe, 1, 0x00,
/* Power control */
CMD, 0xc0, 1, 0x00,
CMD, 0xc1, 1, 0x03,
CMD, 0xc2, 2, 0x73, 0x03,
CMD, 0xc3, 2, 0x73, 0x03,
CMD, 0xc4, 2, 0x73, 0x03,
CMD, 0xc5, 2, 0x64, 0x37,
/* Display control */
CMD, 0xb1, 2, 0x69, 0x13,
CMD, 0xb2, 2, 0x69, 0x13,
CMD, 0xb3, 2, 0x69, 0x13,
CMD, 0xb4, 1, 0x02,
CMD, 0xb6, 2, 0x03, 0x12,
CMD, 0x35, 1, 0x00, /* Tearing Effect Line On */
CMD, 0x26, 1, 0x10, /* Gamma Set */
/* Gamma settings */
CMD, 0xe0, 11, 0x08, 0x00, 0x10, 0x00, 0x03, 0x0e, 0xc8, 0x65,
0x05, 0x00, 0x00,
CMD, 0xe1, 11, 0x06, 0x20, 0x00, 0x00, 0x00, 0x07, 0x4d, 0x0b,
0x08, 0x00, 0x00,
CMD, 0xe2, 11, 0x08, 0x77, 0x27, 0x63, 0x0f, 0x16, 0xcf, 0x25,
0x03, 0x00, 0x00,
CMD, 0xe3, 11, 0x5f, 0x53, 0x77, 0x06, 0x00, 0x02, 0x4b, 0x7b,
0x0f, 0x00, 0x00,
CMD, 0xe4, 11, 0x08, 0x46, 0x57, 0x52, 0x0f, 0x16, 0xcf, 0x25,
0x04, 0x00, 0x00,
CMD, 0xe5, 11, 0x6f, 0x42, 0x57, 0x06, 0x00, 0x04, 0x43, 0x7b,
0x0f, 0x00, 0x00,
CMD, 0x3a, 1, 0x66, /* Pixel Format Set */
CMD, 0x36, 1, 0x60, /* Memory Access Control */
/* Awake sequence */
CMD, 0x11, 0, /* Sleep Out */
SLEEP, 12, /* 120 ms */
CMD, 0x29, 0, /* Display On */
SLEEP, 1, /* 10 ms */
END
};
/* 0xe6 */
static const uint8_t lcd_init_seq_3[] =
{
CMD, 0xef, 1, 0x80,
/* Power control */
CMD, 0xc0, 1, 0x0a,
CMD, 0xc1, 1, 0x03,
CMD, 0xc2, 2, 0x12, 0x00,
CMD, 0xc3, 2, 0x12, 0x00,
CMD, 0xc4, 2, 0x12, 0x00,
CMD, 0xc5, 2, 0x38, 0x38,
/* Display control */
CMD, 0xb1, 2, 0x5f, 0x3f,
CMD, 0xb2, 2, 0x5f, 0x3f,
CMD, 0xb3, 2, 0x5f, 0x3f,
CMD, 0xb4, 1, 0x02,
CMD, 0xb6, 2, 0x12, 0x02,
CMD, 0x35, 1, 0x00, /* Tearing Effect Line On */
CMD, 0x26, 1, 0x10, /* Gamma Set */
CMD, 0xfe, 1, 0x00,
/* Gamma settings */
CMD, 0xe0, 11, 0x0f, 0x70, 0x47, 0x03, 0x02, 0x02, 0xa0, 0x94,
0x05, 0x00, 0x0e,
CMD, 0xe1, 11, 0x02, 0x43, 0x77, 0x00, 0x0f, 0x05, 0x49, 0x0a,
0x02, 0x0e, 0x00,
CMD, 0xe2, 11, 0x2f, 0x63, 0x20, 0x50, 0x00, 0x07, 0xd1, 0x13,
0x00, 0x00, 0x0e,
CMD, 0xe3, 11, 0x50, 0x20, 0x60, 0x23, 0x0f, 0x00, 0x31, 0x1d,
0x07, 0x0e, 0x00,
CMD, 0xe4, 11, 0x5e, 0x50, 0x65, 0x27, 0x00, 0x0b, 0xdf, 0xf1,
0x01, 0x00, 0x0e,
CMD, 0xe5, 11, 0x20, 0x67, 0x55, 0x50, 0x0e, 0x01, 0x1f, 0xfd,
0x0b, 0x0e, 0x00,
CMD, 0x3a, 1, 0x06, /* Pixel Format Set */
CMD, 0x36, 1, 0x60, /* Memory Control Access */
CMD, 0x13, 0, /* Normal Mode On */
/* Awake sequence */
CMD, 0x11, 0, /* Sleep Out */
SLEEP, 12, /* 120 ms */
CMD, 0x29, 0, /* Display On */
SLEEP, 1, /* 10 ms */
END
};
/* 0x58 */
static const uint8_t lcd_init_seq_4[] =
{
CMD, 0xe1, 3, 0x0f, 0x31, 0x04,
CMD, 0xe2, 5, 0x02, 0xa2, 0x08, 0x11, 0x01,
CMD, 0xe3, 2, 0x10, 0x88,
CMD, 0xe4, 2, 0x10, 0x88,
CMD, 0xe5, 2, 0x00, 0x88,
CMD, 0xe7, 13, 0x33, 0x0d, 0x57, 0x0e, 0x57, 0x05, 0x57, 0x02,
0x04, 0x10, 0x0b, 0x02, 0x02,
CMD, 0xe8, 5, 0x30, 0x0d, 0x84, 0x8c, 0x21,
CMD, 0xe9, 5, 0x4b, 0x1a, 0xba, 0x60, 0x11,
CMD, 0xea, 5, 0x4b, 0xba, 0xba, 0x10, 0x11,
CMD, 0xeb, 5, 0x0b, 0x3a, 0xd9, 0x60, 0x11,
CMD, 0xef, 3, 0x00, 0x00, 0x00,
CMD, 0xf0, 18, 0x12, 0x01, 0x21, 0xa5, 0x6c, 0x23, 0x02, 0x01,
0x08, 0x0d, 0x1e, 0xde, 0x5a, 0x93, 0xdc, 0x0d,
0x1e, 0x17,
CMD, 0xf1, 18, 0x12, 0x05, 0x21, 0xb5, 0x8d, 0x24, 0x02, 0x01,
0x08, 0x0d, 0x1a, 0xde, 0x4a, 0x72, 0xdb, 0x0d,
0x1e, 0x17,
CMD, 0xf2, 18, 0x0e, 0x00, 0x30, 0xd6, 0x8f, 0x34, 0x03, 0x07,
0x08, 0x11, 0x1f, 0xcf, 0x29, 0x70, 0xcb, 0x0c,
0x18, 0x17,
CMD, 0xfa, 3, 0x02, 0x00, 0x02,
CMD, 0xf7, 2, 0x00, 0xc0,
CMD, 0x35, 1, 0x00, /* Tearing Effect Line On */
CMD, 0x36, 1, 0x20, /* Memory Access Control */
/* Awake sequence */
CMD, 0x11, 0, /* Sleep Out */
SLEEP, 12, /* 120 ms */
CMD, 0x29, 0, /* Display On */
SLEEP, 1, /* 10 ms */
END
};
static void* seq_init_by_type[] =
{
[LCD_TYPE_38B3] = (void*) lcd_init_seq_0,
[LCD_TYPE_38C4] = (void*) lcd_init_seq_1,
[LCD_TYPE_38D5] = (void*) lcd_init_seq_2,
[LCD_TYPE_38E6] = (void*) lcd_init_seq_3,
[LCD_TYPE_58XX] = (void*) lcd_init_seq_4,
};
#endif /* BOOTLOADER */
static struct lcd_info_rec lcd_info = {
.mpuiface = LCD_MPUIFACE_PAR9,
};
uint8_t lcd_id[4]; // XXX: DEBUG
struct lcd_info_rec* lcd_target_get_info(void)
{
// uint8_t lcd_id[4];
int type = LCD_TYPE_UNKNOWN;
int retry = 3;
while (retry--)
{
lcd_read_display_id(LCD_MPUIFACE_PAR9, &lcd_id[0]); // TODO?: MPUIFACE_PAR9
if (lcd_id[1] == 0x58)
{
type = LCD_TYPE_58XX;
}
else if (lcd_id[1] == 0x38)
{
if (lcd_id[2] == 0xb3) type = LCD_TYPE_38B3;
else if (lcd_id[2] == 0xc4) type = LCD_TYPE_38C4;
else if (lcd_id[2] == 0xd5) type = LCD_TYPE_38D5;
else if (lcd_id[2] == 0xe6) type = LCD_TYPE_38E6;
}
if (type != LCD_TYPE_UNKNOWN)
{
lcd_info.lcd_type = type;
//lcd_info.mpuiface = LCD_MPUIFACE_PAR9;
#if defined(HAVE_LCD_SLEEP) || defined(HAVE_LCD_SHUTDOWN)
lcd_info.seq_sleep = seq_sleep_by_type[type];
#endif
#ifdef HAVE_LCD_SLEEP
lcd_info.seq_awake = seq_awake_by_type[type];
#endif
#ifdef BOOTLOADER
lcd_info.seq_init = seq_init_by_type[type];
#endif
return &lcd_info;
}
}
#ifdef BOOTLOADER
while (1) {
uint16_t fatal[] = { 3000,500,500, 0 };
piezo_seq(fatal);
}
#else
/* should not happen */
while (1); // TODO?: what to do? poweroff?
#endif
}

View file

@ -0,0 +1,34 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: lcd-nano2g.c 28868 2010-12-21 06:59:17Z Buschel $
*
* Copyright (C) 2009 by Dave Chapman
*
* 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 __LCD_TARGET_H__
#define __LCD_TARGET_H__
// #include "config.h"
/* define this to add support for LCDs with 16-bit command set */
// #define S5L_LCD_WITH_CMDSET16
/* define this to include support for LCD read ID command */
#define S5L_LCD_WITH_READID
// struct lcd_info_rec* lcd_target_get_info(void);
#endif /* __LCD_TARGET_H__ */

View file

@ -0,0 +1,63 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 by Michael Sparmann
*
* 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 "mv.h"
int nand_init(void)
{
// TODO
return 0;
}
int nand_read_sectors(IF_MD(int drive,) sector_t start, int incount,
void* inbuf)
{
// TODO
#ifdef HAVE_MULTIDRIVE
(void) drive;
#endif
(void) start;
(void) incount;
(void) inbuf;
return 0;
}
int nand_write_sectors(IF_MD(int drive,) sector_t start, int count,
const void* outbuf)
{
// TODO
#ifdef HAVE_MULTIDRIVE
(void) drive;
#endif
(void) start;
(void) count;
(void) outbuf;
return 0;
}
int nand_event(long id, intptr_t data)
{
// TODO
(void) id;
(void) data;
return 0;
}

View file

@ -0,0 +1,130 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006-2007 Robert Keevil
*
* 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 "kernel.h"
#include "piezo.h"
static unsigned int duration;
static bool beeping;
void INT_TIMERA(void)
{
/* clear interrupt */
TACON = TACON;
if (!(--duration))
piezo_stop();
}
static void piezo_gpio_enable(bool enable)
{
PCON0 = (PCON0 & ~0xff000000) | (enable ? 0x53000000 : 0xee000000);
}
static void piezo_start(unsigned short cycles, unsigned short periods)
{
#ifndef SIMULATOR
duration = periods;
beeping = 1;
/* select TA_OUT function on GPIO ports */
piezo_gpio_enable(true);
/* configure timer for 100 kHz (12 MHz / 4 / 30) */
TACMD = (1 << 1); /* TA_CLR */
TAPRE = 30 - 1; /* prescaler */
TACON = (1 << 13) | /* TA_INT1_EN */
(0 << 12) | /* TA_INT0_EN */
(0 << 11) | /* TA_START */
(1 << 8) | /* TA_CS = ECLK / 4 */
(1 << 6) | /* select ECLK (12 MHz) */
(1 << 4); /* TA_MODE_SEL = PWM mode */
TADATA0 = cycles; /* set interval period */
TADATA1 = cycles << 1; /* set interval period */
TACMD = (1 << 0); /* TA_EN */
#endif
}
void piezo_stop(void)
{
#ifndef SIMULATOR
beeping = 0;
TACMD = (1 << 1); /* TA_CLR */
/* configure GPIO for the lowest power consumption */
piezo_gpio_enable(false);
#endif
}
void piezo_clear(void)
{
piezo_stop();
}
bool piezo_busy(void)
{
return beeping;
}
void piezo_init(void)
{
piezo_stop();
}
void piezo_button_beep(bool beep, bool force)
{
if (force)
while (beeping)
yield();
if (!beeping)
{
if (beep)
piezo_start(22, 457);
else
piezo_start(40, 4);
}
}
#ifdef BOOTLOADER
void piezo_tone(uint32_t period /*uS*/, int32_t duration /*ms*/)
{
int32_t stop = USEC_TIMER + duration*1000;
uint32_t level = 0;
piezo_gpio_enable(true);
while ((int32_t)USEC_TIMER - stop < 0)
{
level ^= 1;
GPIOCMD = 0x0060e | level;
udelay(period >> 1);
}
piezo_gpio_enable(false);
}
void piezo_seq(uint16_t *seq)
{
uint16_t period;
while ((period = *seq++) != 0)
{
piezo_tone(period, *seq++);
udelay(*seq++ * 1000);
}
}
#endif

View file

@ -0,0 +1,37 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006-2007 Robert Keevil
*
* 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 __PIEZO_H__
#define __PIEZO_H__
#include <stdbool.h>
void piezo_init(void);
void piezo_stop(void);
void piezo_clear(void);
bool piezo_busy(void);
void piezo_button_beep(bool beep, bool force);
#ifdef BOOTLOADER
#include <inttypes.h>
void piezo_tone(uint32_t period, int32_t duration);
void piezo_seq(uint16_t *seq);
#endif
#endif /* __PIEZO_H__ */

View file

@ -0,0 +1,366 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: pmu-nano2g.c 27752 2010-08-08 10:49:32Z bertrik $
*
* Copyright © 2008 Rafaël Carré
*
* 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 "kernel.h"
#include "thread.h"
#include "pmu-target.h"
#include "adc-target.h"
#include "i2c-s5l8702.h"
#include "gpio-s5l8702.h"
int pmu_read_multiple(int address, int count, unsigned char* buffer)
{
return i2c_read(0, 0xe6, address, count, buffer);
}
int pmu_write_multiple(int address, int count, unsigned char* buffer)
{
return i2c_write(0, 0xe6, address, count, buffer);
}
unsigned char pmu_read(int address)
{
unsigned char tmp;
pmu_read_multiple(address, 1, &tmp);
return tmp;
}
int pmu_write(int address, unsigned char val)
{
return pmu_write_multiple(address, 1, &val);
}
#if 0
// TODO
void pmu_ldo_on_in_standby(unsigned int ldo, int onoff)
{
if (ldo < 4)
{
unsigned char newval = pmu_read(0x3B) & ~(1 << (2 * ldo));
if (onoff) newval |= 1 << (2 * ldo);
pmu_write(0x3B, newval);
}
else if (ldo < 8)
{
unsigned char newval = pmu_read(0x3C) & ~(1 << (2 * (ldo - 4)));
if (onoff) newval |= 1 << (2 * (ldo - 4));
pmu_write(0x3C, newval);
}
}
void pmu_ldo_set_voltage(unsigned int ldo, unsigned char voltage)
{
if (ldo > 6) return;
pmu_write(0x2d + (ldo << 1), voltage);
}
void pmu_hdd_power(bool on)
{
pmu_write(0x1b, on ? 1 : 0);
}
void pmu_ldo_power_on(unsigned int ldo)
{
if (ldo > 6) return;
pmu_write(0x2e + (ldo << 1), 1);
}
void pmu_ldo_power_off(unsigned int ldo)
{
if (ldo > 6) return;
pmu_write(0x2e + (ldo << 1), 0);
}
#endif
void pmu_set_wake_condition(unsigned char condition)
{
// TODO
(void) condition;
}
void pmu_enter_standby(void)
{
pmu_write(D1671_REG_SYSCTRLA, D1671_SYSCTRLA_GOSTDBY);
}
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
void pmu_set_cpu_voltage(bool high)
{
// TODO
(void) high;
}
#endif
#if (CONFIG_RTC == RTC_NANO3G)
void pmu_read_rtc(unsigned char* buffer)
{
// TODO
(void) buffer;
}
void pmu_write_rtc(unsigned char* buffer)
{
// TODO
(void) buffer;
}
#endif
void pmu_set_usblimit(bool fast_charge)
{
pmu_write(D1671_REG_CHCTL,
(pmu_read(D1671_REG_CHCTL) & ~D1671_CHCTL_FASTCHRG) | fast_charge);
}
/*
* ADC
*/
static struct mutex pmu_adc_mutex;
/* converts raw value to millivolts */
unsigned short pmu_adc_raw2mv(
const struct pmu_adc_channel *ch, unsigned short raw)
{
// TODO
(void) ch;
(void) raw;
return 0;
}
/* returns raw value */
unsigned short pmu_read_adc(const struct pmu_adc_channel *ch)
{
// TODO
int raw = 0;
mutex_lock(&pmu_adc_mutex);
(void) ch;
mutex_unlock(&pmu_adc_mutex);
return raw;
}
/*
* eINT
*/
#define Q_EINT 0
static char pmu_thread_stack[DEFAULT_STACK_SIZE/2];
static struct event_queue pmu_queue;
static unsigned char ints_msk[2];
static void pmu_eint_isr(struct eic_handler*);
static struct eic_handler pmu_eint =
{
.gpio_n = GPIO_EINT_PMU,
.type = EIC_INTTYPE_LEVEL,
.level = EIC_INTLEVEL_LOW,
.isr = pmu_eint_isr,
};
static int pmu_input_holdswitch;
int pmu_holdswitch_locked(void)
{
return pmu_input_holdswitch;
}
#ifdef IPOD_ACCESSORY_PROTOCOL
static int pmu_input_accessory;
int pmu_accessory_present(void)
{
return pmu_input_accessory;
}
#endif
#if CONFIG_CHARGING
static int pmu_input_firewire;
int pmu_firewire_present(void)
{
return pmu_input_firewire;
}
#endif
#if 1 // XXX: from usb-s5l8702.c
#include "usb.h"
static int usb_status = USB_EXTRACTED;
int usb_detect(void)
{
return usb_status;
}
void usb_insert_int(void)
{
usb_status = USB_INSERTED;
}
void usb_remove_int(void)
{
usb_status = USB_EXTRACTED;
}
#endif
static void pmu_read_inputs(void)
{
unsigned char status[2];
pmu_read_multiple(D1671_REG_STATUSA, 2, status);
if (status[0] & D1671_STATUSA_VBUS)
usb_insert_int();
else
usb_remove_int();
#if CONFIG_CHARGING
pmu_input_firewire = !!(status[0] & D1671_STATUSA_VADAPTOR);
#endif
#ifdef IPOD_ACCESSORY_PROTOCOL
pmu_input_accessory = !!(status[0] & D1671_STATUSA_INPUT1);
#endif
pmu_input_holdswitch = !(status[1] & D1671_STATUSB_INPUT2);
}
static void pmu_eint_isr(struct eic_handler *h)
{
eint_unregister(h);
queue_post(&pmu_queue, Q_EINT, 0);
}
static void NORETURN_ATTR pmu_thread(void)
{
struct queue_event ev;
while (true)
{
queue_wait_w_tmo(&pmu_queue, &ev, TIMEOUT_BLOCK);
switch (ev.id)
{
case Q_EINT:
/* clear all PMU interrupts, this will also raise
(disable) the PMU IRQ pin */
pmu_write_multiple(D1671_REG_EVENTA, 2, "\xFF\xFF");
/* get actual values */
pmu_read_inputs();
eint_register(&pmu_eint);
break;
case SYS_TIMEOUT:
break;
}
}
}
/* main init */
void pmu_init(void)
{
mutex_init(&pmu_adc_mutex);
queue_init(&pmu_queue, false);
create_thread(pmu_thread,
pmu_thread_stack, sizeof(pmu_thread_stack), 0,
"PMU" IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU));
/* configure PMU interrutps */
ints_msk[0] = 0xff;
ints_msk[1] = 0xff;
ints_msk[0] &= ~D1671_IRQMASKA_VBUS; /* USB */
#if CONFIG_CHARGING
ints_msk[0] &= ~D1671_IRQMASKA_VADAPTOR; /* FireWire */
#endif
#ifdef IPOD_ACCESSORY_PROTOCOL
ints_msk[0] &= ~D1671_IRQMASKA_INPUT1; /* Accessory */
#endif
ints_msk[1] &= ~D1671_IRQMASKB_INPUT2; /* Holdswitch */
pmu_write_multiple(D1671_REG_IRQMASKA, 2, ints_msk);
/* clear all interrupts */
pmu_write_multiple(D1671_REG_EVENTA, 2, "\xFF\xFF");
/* get initial values */
pmu_read_inputs();
eint_register(&pmu_eint);
}
/*
* preinit
*/
int pmu_rd_multiple(int address, int count, unsigned char* buffer)
{
return i2c_rd(0, 0xe6, address, count, buffer);
}
int pmu_wr_multiple(int address, int count, unsigned char* buffer)
{
return i2c_wr(0, 0xe6, address, count, buffer);
}
unsigned char pmu_rd(int address)
{
unsigned char val;
pmu_rd_multiple(address, 1, &val);
return val;
}
int pmu_wr(int address, unsigned char val)
{
return pmu_wr_multiple(address, 1, &val);
}
void pmu_preinit(void)
{
// TBC: LDOs ???
pmu_wr(0x1b, 0x14);
pmu_wr(0x16, 0x14);
pmu_wr(0x15, 0x14); // TBC: Vnand = 2000 + val*50 = 3000 mV
pmu_wr(0x18, 0x18); // TBC TBC TBC: Vaccy = 3200 mV ???
pmu_wr(0x10, (pmu_rd(0x10) & 0xdb) | 0x8); // TBC: bit4 is related to NAND, LDO_0x15 on/off ???
// TBC: 0x30, 0x31 y 0x32 seems related to ADC (norboot)
pmu_wr(0x34, 0x72); // TBC: en DA9030: TBATHIGH (0-255, TBAT high temperature threshold
pmu_wr(0x30, pmu_rd(0x30) | 0x20); // TBC: TBATREF ON ???
pmu_wr(0x21, 0x5c); // TBC: CHRG_CTL (max. current and Vbat ???)
pmu_wr(0xb, 0x6);
pmu_wr(0x1d, 0);
/* configure and clear interrupts */
pmu_wr_multiple(D1671_REG_IRQMASKA, 2, "\x42\xBE");
pmu_wr_multiple(D1671_REG_EVENTA, 2, "\xFF\xFF");
/* backlight off */
pmu_wr(D1671_REG_LEDCTL, pmu_rd(D1671_REG_LEDCTL) & ~D1671_LEDCTL_ENABLE);
}
#ifdef BOOTLOADER
bool pmu_is_hibernated(void)
{
return !!(pmu_rd(D1671_REG_EVENTB) & D1671_EVENTB_WARMBOOT);
}
#endif

View file

@ -0,0 +1,142 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: pmu-target.h 24721 2010-02-17 15:54:48Z theseven $
*
* Copyright © 2009 Michael Sparmann
*
* 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 __PMU_TARGET_H__
#define __PMU_TARGET_H__
#include <stdint.h>
#include <stdbool.h>
#include "config.h"
/* undocummented PMU registers */
enum d1671_regs {
D1671_REG_EVENTA = 0x02,
D1671_REG_EVENTB = 0x03,
D1671_REG_STATUSA = 0x04,
D1671_REG_STATUSB = 0x05,
D1671_REG_IRQMASKA = 0x06,
D1671_REG_IRQMASKB = 0x07,
D1671_REG_SYSCTRLA = 0x08,
D1671_REG_LEDCTL = 0x20,
D1671_REG_CHCTL = 0x21, // TBC
D1671_REG_RTCSEC = 0x40, // TBC
};
enum d1671_reg_eventa {
D1671_EVENTA_VBUS = 0x08, /* USB: 0 -> not present */
D1671_EVENTA_VADAPTOR = 0x10, /* FireWire: 0 -> not present */
D1671_EVENTA_INPUT1 = 0x20, /* accessory: 0 -> not present */
D1671_EVENTA_UNK6 = 0x40, // ???
};
enum d1671_reg_eventb {
D1671_EVENTB_INPUT2 = 0x01, /* hold switch: 0 -> locked */
D1671_EVENTB_WARMBOOT = 0x80, // TBC
};
enum d1671_reg_statusa {
D1671_STATUSA_VBUS = 0x08,
D1671_STATUSA_VADAPTOR = 0x10,
D1671_STATUSA_INPUT1 = 0x20,
};
enum d1671_reg_statusb {
D1671_STATUSB_INPUT2 = 0x01,
D1671_STATUSB_WARMBOOT = 0x80,
};
enum d1671_reg_irqmaska {
D1671_IRQMASKA_VBUS = 0x08,
D1671_IRQMASKA_VADAPTOR = 0x10,
D1671_IRQMASKA_INPUT1 = 0x20,
};
enum d1671_reg_irqmaskb {
D1671_IRQMASKB_INPUT2 = 0x01,
D1671_IRQMASKB_WARMBOOT = 0x80,
};
enum d1671_reg_sysctrla {
D1671_SYSCTRLA_GOSTDBY = 0x01,
D1671_SYSCTRLA_GOUNK = 0x02, /* enter unknown state (shutdown?) */
};
enum d1671_reg_ledctl {
D1671_LEDCTL_UNKNOWN = 0x40,
D1671_LEDCTL_ENABLE = 0x80,
};
#define D1671_LEDCTL_OUT_POS 0
#define D1671_LEDCTL_OUT_MASK 0x1f
enum d1671_reg_chctl {
D1671_CHCTL_FASTCHRG = 0x01, /* 100/500mA USB limit */
};
/* GPIO for external PMU interrupt */
#define GPIO_EINT_PMU 0x7b
struct pmu_adc_channel
{
const char *name;
// TODO
};
void pmu_preinit(void);
void pmu_init(void);
unsigned char pmu_read(int address);
int pmu_write(int address, unsigned char val);
int pmu_read_multiple(int address, int count, unsigned char* buffer);
int pmu_write_multiple(int address, int count, unsigned char* buffer);
#ifdef BOOTLOADER
unsigned char pmu_rd(int address);
int pmu_wr(int address, unsigned char val);
int pmu_rd_multiple(int address, int count, unsigned char* buffer);
int pmu_wr_multiple(int address, int count, unsigned char* buffer);
bool pmu_is_hibernated(void);
#endif
// void pmu_ldo_on_in_standby(unsigned int ldo, int onoff);
// void pmu_ldo_set_voltage(unsigned int ldo, unsigned char voltage);
// void pmu_ldo_power_on(unsigned int ldo);
// void pmu_ldo_power_off(unsigned int ldo);
void pmu_set_wake_condition(unsigned char condition);
void pmu_enter_standby(void);
// void pmu_nand_power(bool on);
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
void pmu_set_cpu_voltage(bool high);
#endif
#if (CONFIG_RTC == RTC_NANO3G)
void pmu_read_rtc(unsigned char* buffer);
void pmu_write_rtc(unsigned char* buffer);
#endif
void pmu_set_usblimit(bool fast_charge);
unsigned short pmu_read_adc(const struct pmu_adc_channel *ch);
unsigned short pmu_adc_raw2mv(
const struct pmu_adc_channel *ch, unsigned short raw);
int pmu_holdswitch_locked(void);
#if CONFIG_CHARGING
int pmu_firewire_present(void);
#endif
#ifdef IPOD_ACCESSORY_PROTOCOL
int pmu_accessory_present(void);
#endif
#endif /* __PMU_TARGET_H__ */

View file

@ -0,0 +1,67 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: power-nano2g.c 28190 2010-10-01 18:09:10Z Buschel $
*
* Copyright © 2009 Bertrik Sikken
*
* 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 <stdbool.h>
#include "config.h"
#include "inttypes.h"
#include "s5l87xx.h"
#include "power.h"
#include "panic.h"
#include "pmu-target.h"
#include "usb_core.h" /* for usb_charging_maxcurrent_change */
void power_init(void)
{
pmu_init();
pmu_set_usblimit(false); /* limit to 100mA */
}
void power_off(void)
{
pmu_enter_standby();
while(1);
}
#if CONFIG_CHARGING
#ifdef HAVE_USB_CHARGING_ENABLE
void usb_charging_maxcurrent_change(int maxcurrent)
{
bool fast_charge = (maxcurrent >= 500);
pmu_set_usblimit(fast_charge);
}
#endif
unsigned int power_input_status(void)
{
unsigned int status = POWER_INPUT_NONE;
if (usb_detect() == USB_INSERTED)
status |= POWER_INPUT_USB_CHARGER;
if (pmu_firewire_present())
status |= POWER_INPUT_MAIN_CHARGER;
return status;
}
bool charging_state(void)
{
// TODO
return false;
}
#endif /* CONFIG_CHARGING */

View file

@ -0,0 +1,79 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: powermgmt-nano2g.c 28159 2010-09-24 22:42:06Z Buschel $
*
* Copyright © 2008 Rafaël Carré
*
* 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 "powermgmt.h"
#include "pmu-target.h"
#include "power.h"
#include "audiohw.h"
#include "adc-target.h"
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
{
3500
};
const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
{
3300
};
/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
{
{ 3500, 3670, 3720, 3750, 3770, 3800, 3860, 3920, 3980, 4070, 4170 }
};
#if CONFIG_CHARGING
/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
const unsigned short percent_to_volt_charge[11] =
{
3700, 3820, 3900, 3950, 3990, 4030, 4070, 4120, 4170, 4190, 4200
};
#endif /* CONFIG_CHARGING */
/* Returns battery voltage from ADC [millivolts] */
int _battery_voltage(void)
{
return adc_read_battery_voltage();
}
#ifdef HAVE_ACCESSORY_SUPPLY
void accessory_supply_set(bool enable)
{
if (enable)
{
/* Accessory voltage supply on */
}
else
{
/* Accessory voltage supply off */
}
}
#endif
#ifdef HAVE_LINEOUT_POWEROFF
void lineout_set(bool enable)
{
/* Call audio hardware driver implementation */
audiohw_enable_lineout(enable);
}
#endif

View file

@ -0,0 +1,73 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: rtc-nano2g.c 23114 2009-10-11 18:20:56Z theseven $
*
* Copyright (C) 2002 by Linus Nielsen Feltzing, Uwe Freese, Laurent Baum
*
* 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 "rtc.h"
#include "kernel.h"
#include "system.h"
#include "pmu-target.h"
#include "timefuncs.h"
void rtc_init(void)
{
}
int rtc_read_datetime(struct tm *tm)
{
unsigned int i;
unsigned char buf[7];
pmu_read_rtc(buf);
for (i = 0; i < sizeof(buf); i++)
buf[i] = BCD2DEC(buf[i]);
tm->tm_sec = buf[0];
tm->tm_min = buf[1];
tm->tm_hour = buf[2];
tm->tm_mday = buf[4];
tm->tm_mon = buf[5] - 1;
tm->tm_year = buf[6] + 100;
tm->tm_yday = 0; /* Not implemented for now */
set_day_of_week(tm);
return 0;
}
int rtc_write_datetime(const struct tm *tm)
{
unsigned int i;
unsigned char buf[7];
buf[0] = tm->tm_sec;
buf[1] = tm->tm_min;
buf[2] = tm->tm_hour;
buf[3] = tm->tm_wday;
buf[4] = tm->tm_mday;
buf[5] = tm->tm_mon + 1;
buf[6] = tm->tm_year - 100;
for (i = 0; i < sizeof(buf); i++)
buf[i] = DEC2BCD(buf[i]);
pmu_write_rtc(buf);
return 0;
}

View file

@ -0,0 +1,249 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2014 by Cástor Muñoz
*
* 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 <stdint.h>
#include <stdbool.h>
#include "config.h"
#include "cpu.h"
#include "system.h"
#include "serial.h"
#include "s5l87xx.h"
#include "uc87xx.h"
/* Define LOGF_ENABLE to enable logf output in this file */
#define LOGF_ENABLE
#include "logf.h"
/* shall include serial HW configuracion for specific target */
#define IPOD6G_UART_CLK_HZ 12000000 /* external OSC0 ??? */
/* This values below are valid with a UCLK of 12MHz */
#define BRDATA_9600 (77) /* 9615 */
#define BRDATA_19200 (38) /* 19231 */
#define BRDATA_28800 (25) /* 28846 */
#define BRDATA_38400 (19 | (0xc330c << 8)) /* 38305 */
#define BRDATA_57600 (12) /* 57692 */
#define BRDATA_115200 (6 | (0xffffff << 8)) /* 114286 */
extern const struct uartc s5l8702_uartc;
#ifdef IPOD_ACCESSORY_PROTOCOL
static void iap_rx_isr(int, char*, char*, uint32_t);
#endif
struct uartc_port ser_port IDATA_ATTR =
{
/* location */
.uartc = &s5l8702_uartc,
.id = 0,
/* configuration */
.rx_trg = UFCON_RX_FIFO_TRG_4,
.tx_trg = UFCON_TX_FIFO_TRG_EMPTY,
.clksel = UCON_CLKSEL_ECLK,
.clkhz = IPOD6G_UART_CLK_HZ,
/* interrupt callbacks */
#ifdef IPOD_ACCESSORY_PROTOCOL
.rx_cb = iap_rx_isr,
#else
.rx_cb = NULL,
#endif
.tx_cb = NULL, /* polling */
};
/*
* serial driver API
*/
int tx_rdy(void)
{
return uartc_port_tx_ready(&ser_port) ? 1 : 0;
}
void tx_writec(unsigned char c)
{
uartc_port_tx_byte(&ser_port, c);
}
#ifndef IPOD_ACCESSORY_PROTOCOL
void serial_setup(void)
{
uartc_port_open(&ser_port);
/* set a default configuration, Tx and Rx modes are
disabled when the port is initialized */
uartc_port_config(&ser_port, ULCON_DATA_BITS_8,
ULCON_PARITY_NONE, ULCON_STOP_BITS_1);
uartc_port_set_bitrate_raw(&ser_port, BRDATA_115200);
/* enable Tx interrupt request or POLLING mode */
uartc_port_set_tx_mode(&ser_port, UCON_MODE_INTREQ);
logf("[%lu] "MODEL_NAME" port %d ready!", USEC_TIMER, ser_port.id);
}
#else /* IPOD_ACCESSORY_PROTOCOL */
#include "kernel.h"
#include "pmu-target.h"
#include "iap.h"
static enum {
ABR_STATUS_LAUNCHED, /* ST_SYNC */
ABR_STATUS_SYNCING, /* ST_SOF */
ABR_STATUS_DONE
} abr_status;
static int bitrate = 0;
static bool acc_plugged = false;
static void serial_acc_tick(void)
{
bool plugged = pmu_accessory_present();
if (acc_plugged != plugged)
{
acc_plugged = plugged;
if (acc_plugged)
{
uartc_open(ser_port.uartc);
uartc_port_open(&ser_port);
/* set a default configuration, Tx and Rx modes are
disabled when the port is initialized */
uartc_port_config(&ser_port, ULCON_DATA_BITS_8,
ULCON_PARITY_NONE, ULCON_STOP_BITS_1);
uartc_port_set_tx_mode(&ser_port, UCON_MODE_INTREQ);
serial_bitrate(bitrate);
}
else
{
uartc_port_close(&ser_port);
uartc_close(ser_port.uartc);
}
}
}
void serial_setup(void)
{
uartc_close(ser_port.uartc);
tick_add_task(serial_acc_tick);
}
void serial_bitrate(int rate)
{
bitrate = rate;
if (!acc_plugged)
return;
logf("[%lu] serial_bitrate(%d)", USEC_TIMER, rate);
if (rate == 0) {
/* Using auto-bitrate (ABR) to detect accessory Tx speed:
*
* + Here:
* - Disable Rx logic to clean the FIFO and the shift
* register, thus no Rx data interrupts are generated.
* - Launch ABR and wait for a low pulse in Rx line.
*
* + In ISR, when a low pulse is detected (ideally it is the
* start bit of 0xff):
* - Calculate and configure detected speed.
* - Enable Rx to verify that the next received data frame
* is 0x55 or 0xff:
* - If so, it's assumed bit rate is correctly detected,
* it will not be modified until speed is changed using
* RB options menu.
* - If not, reset iAP state machine and launch a new ABR.
*/
uartc_port_set_rx_mode(&ser_port, UCON_MODE_DISABLED);
uartc_port_abr_start(&ser_port);
abr_status = ABR_STATUS_LAUNCHED;
}
else {
uint32_t brdata;
if (rate == 57600) brdata = BRDATA_57600;
else if (rate == 38400) brdata = BRDATA_38400;
else if (rate == 19200) brdata = BRDATA_19200;
else brdata = BRDATA_9600;
uartc_port_abr_stop(&ser_port); /* abort ABR if already launched */
uartc_port_set_bitrate_raw(&ser_port, brdata);
uartc_port_set_rx_mode(&ser_port, UCON_MODE_INTREQ);
abr_status = ABR_STATUS_DONE;
}
}
static void iap_rx_isr(int len, char *data, char *err, uint32_t abr_cnt)
{
/* ignore Rx errors, upper layer will discard bad packets */
(void) err;
static int sync_retry;
if (abr_status == ABR_STATUS_LAUNCHED) {
/* autobauding */
if (abr_cnt) {
#define BR2CNT(s) (IPOD6G_UART_CLK_HZ / (unsigned)(s))
if (abr_cnt < BR2CNT(57600*1.1) || abr_cnt > BR2CNT(9600*0.9)) {
/* detected speed out of range, relaunch ABR */
uartc_port_abr_start(&ser_port);
return;
}
/* valid speed detected, select it */
uint32_t brdata;
if (abr_cnt < BR2CNT(48000)) brdata = BRDATA_57600;
else if (abr_cnt < BR2CNT(33600)) brdata = BRDATA_38400;
else if (abr_cnt < BR2CNT(24000)) brdata = BRDATA_28800;
else if (abr_cnt < BR2CNT(14400)) brdata = BRDATA_19200;
else brdata = BRDATA_9600;
/* set detected speed */
uartc_port_set_bitrate_raw(&ser_port, brdata);
uartc_port_set_rx_mode(&ser_port, UCON_MODE_INTREQ);
/* enter SOF state */
iap_getc(0xff);
abr_status = ABR_STATUS_SYNCING;
sync_retry = 2; /* we are expecting [0xff] 0x55 */
}
}
/* process received data */
while (len--)
{
bool sync_done = !iap_getc(*data++);
if (abr_status == ABR_STATUS_SYNCING)
{
if (sync_done) {
abr_status = ABR_STATUS_DONE;
}
else if (--sync_retry == 0) {
/* invalid speed detected, relaunch ABR
discarding remaining data (if any) */
serial_bitrate(0);
break;
}
}
}
}
#endif /* IPOD_ACCESSORY_PROTOCOL */