mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 10:37:38 -04:00
Gigabeat S:
1) Rework event handling and static registration mechanism. No target- specific code in mc13783 driver. GPIO event driver interfaces more cleanly. 2) Somewhat related - enable thread priority for bootloader which is desireable here (ffs is used for GPIO event enabling anyway and that goes along with priority). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17593 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
5f796087b0
commit
a9c20f5789
19 changed files with 443 additions and 235 deletions
|
@ -679,12 +679,13 @@ target/arm/imx31/gigabeat-s/backlight-imx31.c
|
||||||
target/arm/imx31/gigabeat-s/button-imx31.c
|
target/arm/imx31/gigabeat-s/button-imx31.c
|
||||||
target/arm/imx31/gigabeat-s/clkctl-imx31.c
|
target/arm/imx31/gigabeat-s/clkctl-imx31.c
|
||||||
target/arm/imx31/gigabeat-s/dma_start.c
|
target/arm/imx31/gigabeat-s/dma_start.c
|
||||||
target/arm/imx31/gigabeat-s/gpio-imx31.c
|
|
||||||
target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c
|
target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c
|
||||||
|
target/arm/imx31/gigabeat-s/gpio-imx31.c
|
||||||
target/arm/imx31/gigabeat-s/kernel-imx31.c
|
target/arm/imx31/gigabeat-s/kernel-imx31.c
|
||||||
target/arm/imx31/gigabeat-s/i2c-imx31.c
|
target/arm/imx31/gigabeat-s/i2c-imx31.c
|
||||||
target/arm/imx31/gigabeat-s/i2s-imx31.c
|
target/arm/imx31/gigabeat-s/i2s-imx31.c
|
||||||
target/arm/imx31/gigabeat-s/lcd-imx31.c
|
target/arm/imx31/gigabeat-s/lcd-imx31.c
|
||||||
|
target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c
|
||||||
target/arm/imx31/gigabeat-s/mc13783-imx31.c
|
target/arm/imx31/gigabeat-s/mc13783-imx31.c
|
||||||
target/arm/imx31/gigabeat-s/mmu-imx31.c
|
target/arm/imx31/gigabeat-s/mmu-imx31.c
|
||||||
target/arm/imx31/gigabeat-s/power-imx31.c
|
target/arm/imx31/gigabeat-s/power-imx31.c
|
||||||
|
|
|
@ -67,11 +67,6 @@ enum rtc_registers_indexes
|
||||||
/* was it an alarm that triggered power on ? */
|
/* was it an alarm that triggered power on ? */
|
||||||
static bool alarm_start = false;
|
static bool alarm_start = false;
|
||||||
|
|
||||||
void mc13783_alarm_start(void)
|
|
||||||
{
|
|
||||||
alarm_start = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const unsigned char rtc_registers[RTC_NUM_REGS] =
|
static const unsigned char rtc_registers[RTC_NUM_REGS] =
|
||||||
{
|
{
|
||||||
[RTC_REG_TIME] = MC13783_RTC_TIME,
|
[RTC_REG_TIME] = MC13783_RTC_TIME,
|
||||||
|
@ -122,7 +117,12 @@ static int is_leap_year(int y)
|
||||||
/** Public APIs **/
|
/** Public APIs **/
|
||||||
void rtc_init(void)
|
void rtc_init(void)
|
||||||
{
|
{
|
||||||
/* Nothing to do */
|
/* only needs to be polled on startup */
|
||||||
|
if (mc13783_read(MC13783_INTERRUPT_STATUS1) & MC13783_TODAI)
|
||||||
|
{
|
||||||
|
alarm_start = true;
|
||||||
|
mc13783_write(MC13783_INTERRUPT_STATUS1, MC13783_TODAI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int rtc_read_datetime(unsigned char* buf)
|
int rtc_read_datetime(unsigned char* buf)
|
||||||
|
@ -264,7 +264,9 @@ bool rtc_enable_alarm(bool enable)
|
||||||
bool rtc_check_alarm_started(bool release_alarm)
|
bool rtc_check_alarm_started(bool release_alarm)
|
||||||
{
|
{
|
||||||
bool rc = alarm_start;
|
bool rc = alarm_start;
|
||||||
alarm_start &= ~release_alarm;
|
|
||||||
|
if (release_alarm)
|
||||||
|
alarm_start = false;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@
|
||||||
/* Define the bitmask of modules used */
|
/* Define the bitmask of modules used */
|
||||||
#define SPI_MODULE_MASK (USE_CSPI2_MODULE)
|
#define SPI_MODULE_MASK (USE_CSPI2_MODULE)
|
||||||
#define I2C_MODULE_MASK (USE_I2C1_MODULE)
|
#define I2C_MODULE_MASK (USE_I2C1_MODULE)
|
||||||
|
#define GPIO_EVENT_MASK (USE_GPIO1_EVENTS)
|
||||||
|
|
||||||
/* Define this if target has an additional number of threads specific to it */
|
/* Define this if target has an additional number of threads specific to it */
|
||||||
#define TARGET_EXTRA_THREADS 1
|
#define TARGET_EXTRA_THREADS 1
|
||||||
|
|
|
@ -341,7 +341,14 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (CONFIG_CODEC == SWCODEC)
|
#if (CONFIG_CODEC == SWCODEC)
|
||||||
#ifndef BOOTLOADER
|
#ifdef BOOTLOADER
|
||||||
|
|
||||||
|
#if CONFIG_CPU == IMX31L
|
||||||
|
/* Priority in bootloader is wanted */
|
||||||
|
#define HAVE_PRIORITY_SCHEDULING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* !BOOTLOADER */
|
||||||
|
|
||||||
#define HAVE_EXTENDED_MESSAGING_AND_NAME
|
#define HAVE_EXTENDED_MESSAGING_AND_NAME
|
||||||
|
|
||||||
|
|
|
@ -1270,6 +1270,9 @@ enum mc13783_regs_enum
|
||||||
#define MC13783_TC3PERIODr(x) (((x) & MC13783_TC3PERIOD) >> 21)
|
#define MC13783_TC3PERIODr(x) (((x) & MC13783_TC3PERIOD) >> 21)
|
||||||
#define MC13783_TC3TRIODE (0x1 << 23)
|
#define MC13783_TC3TRIODE (0x1 << 23)
|
||||||
|
|
||||||
|
/* For event enum values which are target-defined */
|
||||||
|
#include "mc13783-target.h"
|
||||||
|
|
||||||
void mc13783_init(void);
|
void mc13783_init(void);
|
||||||
void mc13783_close(void);
|
void mc13783_close(void);
|
||||||
uint32_t mc13783_set(unsigned address, uint32_t bits);
|
uint32_t mc13783_set(unsigned address, uint32_t bits);
|
||||||
|
@ -1281,6 +1284,28 @@ int mc13783_write_regset(const unsigned char *regs, const uint32_t *data, int co
|
||||||
uint32_t mc13783_read(unsigned address);
|
uint32_t mc13783_read(unsigned address);
|
||||||
int mc13783_read_multiple(unsigned start, uint32_t *buffer, int count);
|
int mc13783_read_multiple(unsigned start, uint32_t *buffer, int count);
|
||||||
int mc13783_read_regset(const unsigned char *regs, uint32_t *buffer, int count);
|
int mc13783_read_regset(const unsigned char *regs, uint32_t *buffer, int count);
|
||||||
void mc13783_alarm_start(void);
|
|
||||||
|
/* Statically-registered event enable/disable */
|
||||||
|
enum mc13783_event_sets
|
||||||
|
{
|
||||||
|
MC13783_EVENT_SET0 = 0,
|
||||||
|
MC13783_EVENT_SET1 = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mc13783_event
|
||||||
|
{
|
||||||
|
enum mc13783_event_sets set : 8;
|
||||||
|
uint32_t mask : 24;
|
||||||
|
void (*callback)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mc13783_event_list
|
||||||
|
{
|
||||||
|
unsigned count;
|
||||||
|
const struct mc13783_event *events;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool mc13783_enable_event(enum mc13783_event_ids event);
|
||||||
|
void mc13783_disable_event(enum mc13783_event_ids event);
|
||||||
|
|
||||||
#endif /* _MC13783_H_ */
|
#endif /* _MC13783_H_ */
|
||||||
|
|
|
@ -77,11 +77,11 @@ unsigned short adc_read(int channel)
|
||||||
|
|
||||||
mutex_unlock(&adc_mtx);
|
mutex_unlock(&adc_mtx);
|
||||||
|
|
||||||
/* Channels 0-3/8-11 in ADD1, 0-4/12-15 in ADD2 */
|
/* Channels 0-3/8-11 in ADD1, 4-7/12-15 in ADD2 */
|
||||||
return (channel & 4) ? MC13783_ADD2r(data) : MC13783_ADD1r(data);
|
return (channel & 4) ? MC13783_ADD2r(data) : MC13783_ADD1r(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when conversion is complete */
|
/* Called by mc13783 interrupt thread when conversion is complete */
|
||||||
void adc_done(void)
|
void adc_done(void)
|
||||||
{
|
{
|
||||||
wakeup_signal(&adc_wake);
|
wakeup_signal(&adc_wake);
|
||||||
|
@ -100,7 +100,8 @@ void adc_init(void)
|
||||||
MC13783_RTHEN | MC13783_CHRGICON);
|
MC13783_RTHEN | MC13783_CHRGICON);
|
||||||
/* Enable ADC, set multi-channel mode */
|
/* Enable ADC, set multi-channel mode */
|
||||||
mc13783_write(MC13783_ADC1, MC13783_ADEN);
|
mc13783_write(MC13783_ADC1, MC13783_ADEN);
|
||||||
/* Enable the ADCDONE interrupt - notifications are dispatched by
|
|
||||||
* event handler. */
|
/* Enable ADCDONE event */
|
||||||
mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_ADCDONEM);
|
mc13783_write(MC13783_INTERRUPT_STATUS0, MC13783_ADCDONEI);
|
||||||
|
mc13783_enable_event(MC13783_ADCDONE_EVENT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "backlight-target.h"
|
#include "backlight-target.h"
|
||||||
#include "avic-imx31.h"
|
#include "avic-imx31.h"
|
||||||
#include "clkctl-imx31.h"
|
#include "clkctl-imx31.h"
|
||||||
|
#include "mc13783.h"
|
||||||
|
|
||||||
/* Most code in here is taken from the Linux BSP provided by Freescale
|
/* Most code in here is taken from the Linux BSP provided by Freescale
|
||||||
* Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */
|
* Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */
|
||||||
|
@ -119,6 +120,71 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
|
||||||
int_btn = button;
|
int_btn = button;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool button_hold(void)
|
||||||
|
{
|
||||||
|
return _button_hold();
|
||||||
|
}
|
||||||
|
|
||||||
|
int button_read_device(void)
|
||||||
|
{
|
||||||
|
/* Simple poll of GPIO status */
|
||||||
|
hold_button = _button_hold();
|
||||||
|
|
||||||
|
#ifndef BOOTLOADER
|
||||||
|
/* Backlight hold handling */
|
||||||
|
if (hold_button != hold_button_old)
|
||||||
|
{
|
||||||
|
hold_button_old = hold_button;
|
||||||
|
backlight_hold_changed(hold_button);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Enable the keypad interrupt to cause it to fire if a key is down.
|
||||||
|
* KPP_HANDLER will clear and disable it after the scan. If no key
|
||||||
|
* is depressed then this bit will already be set in waiting for the
|
||||||
|
* first key down event. */
|
||||||
|
KPP_KPSR |= KPP_KPSR_KDIE;
|
||||||
|
|
||||||
|
/* If hold, ignore any pressed button */
|
||||||
|
return hold_button ? BUTTON_NONE : int_btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is called from the mc13783 interrupt thread */
|
||||||
|
void button_power_event(void)
|
||||||
|
{
|
||||||
|
bool pressed =
|
||||||
|
(mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD1S) == 0;
|
||||||
|
|
||||||
|
/* Prevent KPP_HANDLER from changing things */
|
||||||
|
int oldlevel = disable_irq_save();
|
||||||
|
|
||||||
|
if (pressed)
|
||||||
|
{
|
||||||
|
int_btn |= BUTTON_POWER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int_btn &= ~BUTTON_POWER;
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_irq(oldlevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_HEADPHONE_DETECTION
|
||||||
|
/* This is called from the mc13783 interrupt thread */
|
||||||
|
void headphone_detect_event(void)
|
||||||
|
{
|
||||||
|
/* FIXME: Not really the correct method */
|
||||||
|
headphones_detect =
|
||||||
|
(mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD2S) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool headphones_inserted(void)
|
||||||
|
{
|
||||||
|
return headphones_detect;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_HEADPHONE_DETECTION */
|
||||||
|
|
||||||
void button_init_device(void)
|
void button_init_device(void)
|
||||||
{
|
{
|
||||||
#ifdef BOOTLOADER
|
#ifdef BOOTLOADER
|
||||||
|
@ -154,6 +220,14 @@ void button_init_device(void)
|
||||||
|
|
||||||
/* KPP IRQ at priority 3 */
|
/* KPP IRQ at priority 3 */
|
||||||
avic_enable_int(KPP, IRQ, 3, KPP_HANDLER);
|
avic_enable_int(KPP, IRQ, 3, KPP_HANDLER);
|
||||||
|
|
||||||
|
button_power_event();
|
||||||
|
mc13783_enable_event(MC13783_ONOFD1_EVENT);
|
||||||
|
|
||||||
|
#ifdef HAVE_HEADPHONE_DETECTION
|
||||||
|
headphone_detect_event();
|
||||||
|
mc13783_enable_event(MC13783_ONOFD2_EVENT);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BUTTON_DRIVER_CLOSE
|
#ifdef BUTTON_DRIVER_CLOSE
|
||||||
|
@ -168,66 +242,3 @@ void button_close_device(void)
|
||||||
restore_irq(oldlevel);
|
restore_irq(oldlevel);
|
||||||
}
|
}
|
||||||
#endif /* BUTTON_DRIVER_CLOSE */
|
#endif /* BUTTON_DRIVER_CLOSE */
|
||||||
|
|
||||||
bool button_hold(void)
|
|
||||||
{
|
|
||||||
return _button_hold();
|
|
||||||
}
|
|
||||||
|
|
||||||
int button_read_device(void)
|
|
||||||
{
|
|
||||||
/* Simple poll of GPIO status */
|
|
||||||
hold_button = _button_hold();
|
|
||||||
|
|
||||||
#ifndef BOOTLOADER
|
|
||||||
/* Backlight hold handling */
|
|
||||||
if (hold_button != hold_button_old)
|
|
||||||
{
|
|
||||||
hold_button_old = hold_button;
|
|
||||||
backlight_hold_changed(hold_button);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Enable the keypad interrupt to cause it to fire if a key is down.
|
|
||||||
* KPP_HANDLER will clear and disable it after the scan. If no key
|
|
||||||
* is depressed then this bit will already be set in waiting for the
|
|
||||||
* first key down event. */
|
|
||||||
KPP_KPSR |= KPP_KPSR_KDIE;
|
|
||||||
|
|
||||||
/* If hold, ignore any pressed button */
|
|
||||||
return hold_button ? BUTTON_NONE : int_btn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is called from the mc13783 interrupt thread */
|
|
||||||
void button_power_set_state(bool pressed)
|
|
||||||
{
|
|
||||||
/* Prevent KPP_HANDLER from changing things */
|
|
||||||
int oldlevel = disable_irq_save();
|
|
||||||
|
|
||||||
if (pressed)
|
|
||||||
{
|
|
||||||
int_btn |= BUTTON_POWER;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int_btn &= ~BUTTON_POWER;
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_irq(oldlevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_HEADPHONE_DETECTION
|
|
||||||
/* This is called from the mc13783 interrupt thread */
|
|
||||||
void set_headphones_inserted(bool inserted)
|
|
||||||
{
|
|
||||||
headphones_detect = inserted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is called from the mc13783 interrupt thread */
|
|
||||||
/* TODO: Just do a post to the button queue directly - implement the
|
|
||||||
* appropriate variant in the driver. */
|
|
||||||
bool headphones_inserted(void)
|
|
||||||
{
|
|
||||||
return headphones_detect;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_HEADPHONE_DETECTION */
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ bool button_hold(void);
|
||||||
void button_init_device(void);
|
void button_init_device(void);
|
||||||
void button_close_device(void);
|
void button_close_device(void);
|
||||||
int button_read_device(void);
|
int button_read_device(void);
|
||||||
void button_power_set_state(bool pressed);
|
void button_power_event(void);
|
||||||
void set_headphones_inserted(bool inserted);
|
void headphone_detect_event(void);
|
||||||
bool headphones_inserted(void);
|
bool headphones_inserted(void);
|
||||||
|
|
||||||
/* Toshiba Gigabeat S-specific button codes */
|
/* Toshiba Gigabeat S-specific button codes */
|
||||||
|
|
|
@ -22,18 +22,23 @@
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "gpio-imx31.h"
|
#include "gpio-imx31.h"
|
||||||
|
|
||||||
extern int mc13783_event(void);
|
/* Gigabeat S definitions for static GPIO event registration */
|
||||||
|
|
||||||
static const struct gpio_event gpio1_events =
|
/* Describes single events for each GPIO1 pin */
|
||||||
|
static const struct gpio_event gpio1_events[] =
|
||||||
{
|
{
|
||||||
.line = MC13783_GPIO_LINE,
|
[MC13783_EVENT_ID-GPIO1_EVENT_FIRST] =
|
||||||
|
{
|
||||||
|
.mask = 1 << MC13783_GPIO_LINE,
|
||||||
.sense = GPIO_SENSE_RISING,
|
.sense = GPIO_SENSE_RISING,
|
||||||
.callback = mc13783_event,
|
.callback = mc13783_event,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Describes the events attached to GPIO1 port */
|
||||||
const struct gpio_event_list gpio1_event_list =
|
const struct gpio_event_list gpio1_event_list =
|
||||||
{
|
{
|
||||||
.priority = 7,
|
.ints_priority = 7,
|
||||||
.count = 1,
|
.count = ARRAYLEN(gpio1_events),
|
||||||
.events = &gpio1_events,
|
.events = gpio1_events,
|
||||||
};
|
};
|
||||||
|
|
|
@ -73,29 +73,38 @@ static struct gpio_module_descriptor
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static void gpio_call_events(enum gpio_module_number gpio)
|
static void gpio_call_events(const struct gpio_module_descriptor * const desc)
|
||||||
{
|
{
|
||||||
const struct gpio_module_descriptor * const desc = &gpio_descs[gpio];
|
|
||||||
const struct gpio_event_list * const list = desc->list;
|
const struct gpio_event_list * const list = desc->list;
|
||||||
struct gpio_map * const base = desc->base;
|
struct gpio_map * const base = desc->base;
|
||||||
unsigned i;
|
const struct gpio_event * event, *event_last;
|
||||||
|
|
||||||
/* Intersect pending and unmasked bits */
|
/* Intersect pending and unmasked bits */
|
||||||
uint32_t pending = base->isr & base->imr;
|
uint32_t pnd = base->isr & base->imr;
|
||||||
|
|
||||||
|
event = list->events;
|
||||||
|
event_last = event + list->count;
|
||||||
|
|
||||||
/* Call each event handler in order */
|
/* Call each event handler in order */
|
||||||
for (i = 0; i < list->count; i++)
|
/* .count is surely expected to be > 0 */
|
||||||
|
do
|
||||||
{
|
{
|
||||||
const struct gpio_event * const event = &list->events[i];
|
uint32_t mask = event->mask;
|
||||||
uint32_t bit = 1ul << event->line;
|
|
||||||
|
|
||||||
if ((pending & bit) && event->callback())
|
if (pnd & mask)
|
||||||
pending &= ~bit;
|
{
|
||||||
|
event->callback();
|
||||||
|
pnd &= ~mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pending != 0)
|
if (pnd == 0)
|
||||||
|
break; /* Teminate early if nothing more to service */
|
||||||
|
}
|
||||||
|
while (++event < event_last);
|
||||||
|
|
||||||
|
if (pnd != 0)
|
||||||
{
|
{
|
||||||
/* Wasn't handled */
|
/* One or more weren't handled */
|
||||||
UIE_VECTOR();
|
UIE_VECTOR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,21 +112,21 @@ static void gpio_call_events(enum gpio_module_number gpio)
|
||||||
#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
|
#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
|
||||||
static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void)
|
static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void)
|
||||||
{
|
{
|
||||||
gpio_call_events(GPIO1_NUM);
|
gpio_call_events(&gpio_descs[GPIO1_NUM]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
|
#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
|
||||||
static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void)
|
static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void)
|
||||||
{
|
{
|
||||||
gpio_call_events(GPIO2_NUM);
|
gpio_call_events(&gpio_descs[GPIO2_NUM]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
|
#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
|
||||||
static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void)
|
static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void)
|
||||||
{
|
{
|
||||||
gpio_call_events(GPIO3_NUM);
|
gpio_call_events(&gpio_descs[GPIO3_NUM]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -140,19 +149,16 @@ void gpio_init(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gpio_enable_event(enum gpio_module_number gpio, unsigned id)
|
bool gpio_enable_event(enum gpio_event_ids id)
|
||||||
{
|
{
|
||||||
const struct gpio_module_descriptor * const desc = &gpio_descs[gpio];
|
const struct gpio_module_descriptor * const desc = &gpio_descs[id >> 5];
|
||||||
const struct gpio_event * const event = &desc->list->events[id];
|
const struct gpio_event * const event = &desc->list->events[id & 31];
|
||||||
struct gpio_map * const base = desc->base;
|
struct gpio_map * const base = desc->base;
|
||||||
volatile uint32_t *icr;
|
volatile uint32_t *icr;
|
||||||
uint32_t mask;
|
uint32_t mask, line;
|
||||||
uint32_t imr;
|
uint32_t imr;
|
||||||
int shift;
|
int shift;
|
||||||
|
|
||||||
if (id >= desc->list->count)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int oldlevel = disable_irq_save();
|
int oldlevel = disable_irq_save();
|
||||||
|
|
||||||
imr = base->imr;
|
imr = base->imr;
|
||||||
|
@ -160,39 +166,37 @@ bool gpio_enable_event(enum gpio_module_number gpio, unsigned id)
|
||||||
if (imr == 0)
|
if (imr == 0)
|
||||||
{
|
{
|
||||||
/* First enabled interrupt for this GPIO */
|
/* First enabled interrupt for this GPIO */
|
||||||
avic_enable_int(desc->ints, IRQ, desc->list->priority,
|
avic_enable_int(desc->ints, IRQ, desc->list->ints_priority,
|
||||||
desc->handler);
|
desc->handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the line sense */
|
/* Set the line sense */
|
||||||
icr = &base->icr[event->line >> 4];
|
line = find_first_set_bit(event->mask);
|
||||||
shift = (event->line & 15) << 1;
|
icr = &base->icr[line >> 4];
|
||||||
|
shift = (line & 15) << 1;
|
||||||
mask = GPIO_SENSE_CONFIG_MASK << shift;
|
mask = GPIO_SENSE_CONFIG_MASK << shift;
|
||||||
|
|
||||||
*icr = (*icr & ~mask) | ((event->sense << shift) & mask);
|
*icr = (*icr & ~mask) | ((event->sense << shift) & mask);
|
||||||
|
|
||||||
/* Unmask the line */
|
/* Unmask the line */
|
||||||
base->imr = imr | (1ul << event->line);
|
base->imr = imr | event->mask;
|
||||||
|
|
||||||
restore_irq(oldlevel);
|
restore_irq(oldlevel);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_disable_event(enum gpio_module_number gpio, unsigned id)
|
void gpio_disable_event(enum gpio_event_ids id)
|
||||||
{
|
{
|
||||||
const struct gpio_module_descriptor * const desc = &gpio_descs[gpio];
|
const struct gpio_module_descriptor * const desc = &gpio_descs[id >> 5];
|
||||||
const struct gpio_event * const event = &desc->list->events[id];
|
const struct gpio_event * const event = &desc->list->events[id & 31];
|
||||||
struct gpio_map * const base = desc->base;
|
struct gpio_map * const base = desc->base;
|
||||||
uint32_t imr;
|
uint32_t imr;
|
||||||
|
|
||||||
if (id >= desc->list->count)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int oldlevel = disable_irq_save();
|
int oldlevel = disable_irq_save();
|
||||||
|
|
||||||
/* Remove bit from mask */
|
/* Remove bit from mask */
|
||||||
imr = base->imr & ~(1ul << event->line);
|
imr = base->imr & ~event->mask;
|
||||||
|
|
||||||
/* Mask the line */
|
/* Mask the line */
|
||||||
base->imr = imr;
|
base->imr = imr;
|
||||||
|
|
|
@ -19,12 +19,12 @@
|
||||||
#ifndef GPIO_IMX31_H
|
#ifndef GPIO_IMX31_H
|
||||||
#define GPIO_IMX31_H
|
#define GPIO_IMX31_H
|
||||||
|
|
||||||
#include "gpio-target.h"
|
/* Static registration mechanism for imx31 GPIO interrupts */
|
||||||
|
|
||||||
#define USE_GPIO1_EVENTS (1 << 0)
|
#define USE_GPIO1_EVENTS (1 << 0)
|
||||||
#define USE_GPIO2_EVENTS (1 << 1)
|
#define USE_GPIO2_EVENTS (1 << 1)
|
||||||
#define USE_GPIO3_EVENTS (1 << 2)
|
#define USE_GPIO3_EVENTS (1 << 2)
|
||||||
|
|
||||||
|
/* Module indexes defined by which GPIO modules are used */
|
||||||
enum gpio_module_number
|
enum gpio_module_number
|
||||||
{
|
{
|
||||||
__GPIO_NUM_START = -1,
|
__GPIO_NUM_START = -1,
|
||||||
|
@ -40,6 +40,22 @@ enum gpio_module_number
|
||||||
GPIO_NUM_GPIO,
|
GPIO_NUM_GPIO,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Module corresponding to the event ID is identified by range */
|
||||||
|
enum gpio_event_bases
|
||||||
|
{
|
||||||
|
#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
|
||||||
|
GPIO1_EVENT_FIRST = 32*GPIO1_NUM,
|
||||||
|
#endif
|
||||||
|
#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
|
||||||
|
GPIO2_EVENT_FIRST = 32*GPIO2_NUM,
|
||||||
|
#endif
|
||||||
|
#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
|
||||||
|
GPIO3_EVENT_FIRST = 32*GPIO3_NUM,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "gpio-target.h"
|
||||||
|
|
||||||
/* Possible values for gpio interrupt line config */
|
/* Possible values for gpio interrupt line config */
|
||||||
enum gpio_int_sense_enum
|
enum gpio_int_sense_enum
|
||||||
{
|
{
|
||||||
|
@ -57,32 +73,40 @@ struct gpio_map
|
||||||
volatile uint32_t dr; /* 00h */
|
volatile uint32_t dr; /* 00h */
|
||||||
volatile uint32_t gdir; /* 04h */
|
volatile uint32_t gdir; /* 04h */
|
||||||
volatile uint32_t psr; /* 08h */
|
volatile uint32_t psr; /* 08h */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
volatile uint32_t icr1; /* 0Ch */
|
||||||
|
volatile uint32_t icr2; /* 10h */
|
||||||
|
};
|
||||||
volatile uint32_t icr[2]; /* 0Ch */
|
volatile uint32_t icr[2]; /* 0Ch */
|
||||||
|
};
|
||||||
volatile uint32_t imr; /* 14h */
|
volatile uint32_t imr; /* 14h */
|
||||||
volatile uint32_t isr; /* 18h */
|
volatile uint32_t isr; /* 18h */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Pending events will be called in array order */
|
/* Pending events will be called in array order which allows easy
|
||||||
|
* pioritization */
|
||||||
|
|
||||||
/* Describes a single event for a pin */
|
/* Describes a single event for a pin */
|
||||||
struct gpio_event
|
struct gpio_event
|
||||||
{
|
{
|
||||||
int line; /* Line number (0-31) */
|
uint32_t mask; /* mask: 1 << (0...31) */
|
||||||
enum gpio_int_sense_enum sense; /* Type of sense */
|
enum gpio_int_sense_enum sense; /* Type of sense */
|
||||||
int (*callback)(void); /* Callback function (return nonzero
|
void (*callback)(void); /* Callback function */
|
||||||
* to indicate this event was handled) */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Describes the events attached to a port */
|
/* Describes the events attached to a port */
|
||||||
struct gpio_event_list
|
struct gpio_event_list
|
||||||
{
|
{
|
||||||
int priority; /* Interrupt priority for this GPIO */
|
int ints_priority; /* Interrupt priority for this GPIO */
|
||||||
unsigned count; /* Count of events */
|
unsigned count; /* Count of events for the module */
|
||||||
const struct gpio_event *events; /* List of events */
|
const struct gpio_event *events; /* List of events */
|
||||||
};
|
};
|
||||||
|
|
||||||
void gpio_init(void);
|
void gpio_init(void);
|
||||||
bool gpio_enable_event(enum gpio_module_number gpio, unsigned id);
|
bool gpio_enable_event(enum gpio_event_ids id);
|
||||||
void gpio_disable_event(enum gpio_module_number gpio, unsigned id);
|
void gpio_disable_event(enum gpio_event_ids id);
|
||||||
|
|
||||||
#endif /* GPIO_IMX31_H */
|
#endif /* GPIO_IMX31_H */
|
||||||
|
|
|
@ -21,11 +21,22 @@
|
||||||
#ifndef GPIO_TARGET_H
|
#ifndef GPIO_TARGET_H
|
||||||
#define GPIO_TARGET_H
|
#define GPIO_TARGET_H
|
||||||
|
|
||||||
#define GPIO_EVENT_MASK (USE_GPIO1_EVENTS)
|
/* MC13783 GPIO pin info for this target */
|
||||||
|
|
||||||
#define MC13783_GPIO_NUM GPIO1_NUM
|
#define MC13783_GPIO_NUM GPIO1_NUM
|
||||||
#define MC13783_GPIO_ISR GPIO1_ISR
|
#define MC13783_GPIO_ISR GPIO1_ISR
|
||||||
#define MC13783_GPIO_LINE 31
|
#define MC13783_GPIO_LINE 31
|
||||||
#define MC13783_EVENT_ID 0
|
|
||||||
|
/* Declare event indexes in priority order in a packed array */
|
||||||
|
enum gpio_event_ids
|
||||||
|
{
|
||||||
|
/* GPIO1 event IDs */
|
||||||
|
MC13783_EVENT_ID = GPIO1_EVENT_FIRST,
|
||||||
|
/* GPIO2 event IDs */
|
||||||
|
/* none defined */
|
||||||
|
/* GPIO3 event IDs */
|
||||||
|
/* none defined */
|
||||||
|
};
|
||||||
|
|
||||||
|
void mc13783_event(void);
|
||||||
|
|
||||||
#endif /* GPIO_TARGET_H */
|
#endif /* GPIO_TARGET_H */
|
||||||
|
|
72
firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c
Normal file
72
firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 by Michael Sevakis
|
||||||
|
*
|
||||||
|
* Gigabeat S MC13783 event descriptions
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* 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 "mc13783.h"
|
||||||
|
#include "mc13783-target.h"
|
||||||
|
#include "adc-target.h"
|
||||||
|
#include "button-target.h"
|
||||||
|
#include "usb-target.h"
|
||||||
|
#include "power-imx31.h"
|
||||||
|
|
||||||
|
/* Gigabeat S definitions for static MC13783 event registration */
|
||||||
|
|
||||||
|
static const struct mc13783_event mc13783_events[] =
|
||||||
|
{
|
||||||
|
[MC13783_ADCDONE_EVENT] = /* ADC conversion complete */
|
||||||
|
{
|
||||||
|
.set = MC13783_EVENT_SET0,
|
||||||
|
.mask = MC13783_ADCDONEM,
|
||||||
|
.callback = adc_done,
|
||||||
|
},
|
||||||
|
[MC13783_ONOFD1_EVENT] = /* Power button */
|
||||||
|
{
|
||||||
|
.set = MC13783_EVENT_SET1,
|
||||||
|
.mask = MC13783_ONOFD1M,
|
||||||
|
.callback = button_power_event,
|
||||||
|
},
|
||||||
|
#ifdef HAVE_HEADPHONE_DETECTION
|
||||||
|
[MC13783_ONOFD2_EVENT] = /* Headphone jack */
|
||||||
|
{
|
||||||
|
.set = MC13783_EVENT_SET1,
|
||||||
|
.mask = MC13783_ONOFD2M,
|
||||||
|
.callback = headphone_detect_event,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
[MC13783_CHGDET_EVENT] = /* Charger detection */
|
||||||
|
{
|
||||||
|
.set = MC13783_EVENT_SET0,
|
||||||
|
.mask = MC13783_CHGDETM,
|
||||||
|
.callback = charger_detect_event,
|
||||||
|
},
|
||||||
|
[MC13783_USB4V4_EVENT] = /* USB insertion */
|
||||||
|
{
|
||||||
|
.set = MC13783_EVENT_SET0,
|
||||||
|
.mask = MC13783_USB4V4M,
|
||||||
|
.callback = usb_connect_event,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct mc13783_event_list mc13783_event_list =
|
||||||
|
{
|
||||||
|
.count = ARRAYLEN(mc13783_events),
|
||||||
|
.events = mc13783_events
|
||||||
|
};
|
|
@ -49,121 +49,86 @@ static struct spi_node mc13783_spi =
|
||||||
0, /* SPI clock - no wait states */
|
0, /* SPI clock - no wait states */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)];
|
extern const struct mc13783_event_list mc13783_event_list;
|
||||||
|
|
||||||
|
static int mc13783_thread_stack[3*DEFAULT_STACK_SIZE/sizeof(int)];
|
||||||
static const char *mc13783_thread_name = "pmic";
|
static const char *mc13783_thread_name = "pmic";
|
||||||
static struct wakeup mc13783_wake;
|
static struct wakeup mc13783_wake;
|
||||||
|
|
||||||
|
/* Tracking for which interrupts are enabled */
|
||||||
|
static uint32_t pmic_int_enabled[2] =
|
||||||
|
{ 0x00000000, 0x00000000 };
|
||||||
|
|
||||||
|
static const unsigned char pmic_intm_regs[2] =
|
||||||
|
{ MC13783_INTERRUPT_MASK0, MC13783_INTERRUPT_MASK1 };
|
||||||
|
|
||||||
|
static const unsigned char pmic_ints_regs[2] =
|
||||||
|
{ MC13783_INTERRUPT_STATUS0, MC13783_INTERRUPT_STATUS1 };
|
||||||
|
|
||||||
#ifdef PMIC_DRIVER_CLOSE
|
#ifdef PMIC_DRIVER_CLOSE
|
||||||
static bool pmic_close = false;
|
static bool pmic_close = false;
|
||||||
static struct thread_entry *mc13783_thread_p = NULL;
|
static struct thread_entry *mc13783_thread_p = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The next two functions are rather target-specific but they'll just be left
|
|
||||||
* here for the moment */
|
|
||||||
static void mc13783_interrupt_thread(void)
|
static void mc13783_interrupt_thread(void)
|
||||||
{
|
{
|
||||||
const unsigned char status_regs[2] =
|
|
||||||
{
|
|
||||||
MC13783_INTERRUPT_STATUS0,
|
|
||||||
MC13783_INTERRUPT_STATUS1,
|
|
||||||
};
|
|
||||||
uint32_t pending[2];
|
uint32_t pending[2];
|
||||||
uint32_t value;
|
|
||||||
|
|
||||||
mc13783_read_regset(status_regs, pending, 2);
|
/* Enable mc13783 GPIO event */
|
||||||
mc13783_write_regset(status_regs, pending, 2);
|
gpio_enable_event(MC13783_EVENT_ID);
|
||||||
|
|
||||||
gpio_enable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID);
|
|
||||||
|
|
||||||
if (pending[1] & MC13783_TODAI) /* only needs to be polled on startup */
|
|
||||||
mc13783_alarm_start();
|
|
||||||
|
|
||||||
/* Check initial states for events with a sense bit */
|
|
||||||
value = mc13783_read(MC13783_INTERRUPT_SENSE0);
|
|
||||||
usb_set_status(value & MC13783_USB4V4S);
|
|
||||||
set_charger_inserted(value & MC13783_CHGDETS);
|
|
||||||
|
|
||||||
value = mc13783_read(MC13783_INTERRUPT_SENSE1);
|
|
||||||
button_power_set_state((value & MC13783_ONOFD1S) == 0);
|
|
||||||
#ifdef HAVE_HEADPHONE_DETECTION
|
|
||||||
set_headphones_inserted((value & MC13783_ONOFD2S) == 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pending[0] = pending[1] = 0xffffff;
|
|
||||||
mc13783_write_regset(status_regs, pending, 2);
|
|
||||||
|
|
||||||
/* Enable desired PMIC interrupts - some are unmasked in the drivers that
|
|
||||||
* handle a specific task */
|
|
||||||
mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_CHGDETM);
|
|
||||||
mc13783_clear(MC13783_INTERRUPT_MASK1, MC13783_ONOFD1M |
|
|
||||||
MC13783_ONOFD2M);
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
const struct mc13783_event *event, *event_last;
|
||||||
|
|
||||||
wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK);
|
wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK);
|
||||||
|
|
||||||
#ifdef PMIC_DRIVER_CLOSE
|
#ifdef PMIC_DRIVER_CLOSE
|
||||||
if (pmic_close)
|
if (pmic_close)
|
||||||
{
|
break;
|
||||||
gpio_disable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mc13783_read_regset(status_regs, pending, 2);
|
mc13783_read_regset(pmic_ints_regs, pending, 2);
|
||||||
mc13783_write_regset(status_regs, pending, 2);
|
|
||||||
|
|
||||||
if (pending[0])
|
/* Only clear interrupts being dispatched */
|
||||||
|
pending[0] &= pmic_int_enabled[0];
|
||||||
|
pending[1] &= pmic_int_enabled[1];
|
||||||
|
|
||||||
|
mc13783_write_regset(pmic_ints_regs, pending, 2);
|
||||||
|
|
||||||
|
event = mc13783_event_list.events;
|
||||||
|
event_last = event + mc13783_event_list.count;
|
||||||
|
|
||||||
|
/* .count is surely expected to be > 0 */
|
||||||
|
do
|
||||||
{
|
{
|
||||||
/* Handle ...PENDING0 */
|
enum mc13783_event_sets set = event->set;
|
||||||
|
uint32_t pnd = pending[set];
|
||||||
|
uint32_t mask = event->mask;
|
||||||
|
|
||||||
/* Handle interrupts without a sense bit */
|
if (pnd & mask)
|
||||||
if (pending[0] & MC13783_ADCDONEI)
|
|
||||||
adc_done();
|
|
||||||
|
|
||||||
/* Handle interrupts that have a sense bit that needs to
|
|
||||||
* be checked */
|
|
||||||
if (pending[0] & (MC13783_CHGDETI | MC13783_USB4V4I))
|
|
||||||
{
|
{
|
||||||
value = mc13783_read(MC13783_INTERRUPT_SENSE0);
|
event->callback();
|
||||||
|
pnd &= ~mask;
|
||||||
if (pending[0] & MC13783_CHGDETI)
|
pending[set] = pnd;
|
||||||
set_charger_inserted(value & MC13783_CHGDETS);
|
|
||||||
|
|
||||||
if (pending[0] & MC13783_USB4V4I)
|
|
||||||
usb_set_status(value & MC13783_USB4V4S);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pending[1])
|
if ((pending[0] | pending[1]) == 0)
|
||||||
{
|
break; /* Teminate early if nothing more to service */
|
||||||
/* Handle ...PENDING1 */
|
}
|
||||||
|
while (++event < event_last);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle interrupts without a sense bit */
|
#ifdef PMIC_DRIVER_CLOSE
|
||||||
/* ... */
|
gpio_disable_event(MC13783_EVENT_ID);
|
||||||
|
|
||||||
/* Handle interrupts that have a sense bit that needs to
|
|
||||||
* be checked */
|
|
||||||
if (pending[1] & (MC13783_ONOFD1I | MC13783_ONOFD2I))
|
|
||||||
{
|
|
||||||
value = mc13783_read(MC13783_INTERRUPT_SENSE1);
|
|
||||||
|
|
||||||
if (pending[1] & MC13783_ONOFD1I)
|
|
||||||
button_power_set_state((value & MC13783_ONOFD1S) == 0);
|
|
||||||
#ifdef HAVE_HEADPHONE_DETECTION
|
|
||||||
if (pending[1] & MC13783_ONOFD2I)
|
|
||||||
set_headphones_inserted((value & MC13783_ONOFD2S) == 0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* GPIO interrupt handler for mc13783 */
|
/* GPIO interrupt handler for mc13783 */
|
||||||
int mc13783_event(void)
|
void mc13783_event(void)
|
||||||
{
|
{
|
||||||
MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE);
|
MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE);
|
||||||
wakeup_signal(&mc13783_wake);
|
wakeup_signal(&mc13783_wake);
|
||||||
return 1; /* Yes, it's handled */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mc13783_init(void)
|
void mc13783_init(void)
|
||||||
|
@ -174,8 +139,8 @@ void mc13783_init(void)
|
||||||
/* Enable the PMIC SPI module */
|
/* Enable the PMIC SPI module */
|
||||||
spi_enable_module(&mc13783_spi);
|
spi_enable_module(&mc13783_spi);
|
||||||
|
|
||||||
/* Mask any PMIC interrupts for now - poll initial status in thread
|
/* Mask any PMIC interrupts for now - modules will enable them as
|
||||||
* and enable them there */
|
* required */
|
||||||
mc13783_write(MC13783_INTERRUPT_MASK0, 0xffffff);
|
mc13783_write(MC13783_INTERRUPT_MASK0, 0xffffff);
|
||||||
mc13783_write(MC13783_INTERRUPT_MASK1, 0xffffff);
|
mc13783_write(MC13783_INTERRUPT_MASK1, 0xffffff);
|
||||||
|
|
||||||
|
@ -203,7 +168,39 @@ void mc13783_close(void)
|
||||||
wakeup_signal(&mc13783_wake);
|
wakeup_signal(&mc13783_wake);
|
||||||
thread_wait(thread);
|
thread_wait(thread);
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* PMIC_DRIVER_CLOSE */
|
||||||
|
|
||||||
|
bool mc13783_enable_event(enum mc13783_event_ids id)
|
||||||
|
{
|
||||||
|
const struct mc13783_event * const event =
|
||||||
|
&mc13783_event_list.events[id];
|
||||||
|
int set = event->set;
|
||||||
|
uint32_t mask = event->mask;
|
||||||
|
|
||||||
|
spi_lock(&mc13783_spi);
|
||||||
|
|
||||||
|
pmic_int_enabled[set] |= mask;
|
||||||
|
mc13783_clear(pmic_intm_regs[set], mask);
|
||||||
|
|
||||||
|
spi_unlock(&mc13783_spi);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mc13783_disable_event(enum mc13783_event_ids id)
|
||||||
|
{
|
||||||
|
const struct mc13783_event * const event =
|
||||||
|
&mc13783_event_list.events[id];
|
||||||
|
int set = event->set;
|
||||||
|
uint32_t mask = event->mask;
|
||||||
|
|
||||||
|
spi_lock(&mc13783_spi);
|
||||||
|
|
||||||
|
pmic_int_enabled[set] &= ~mask;
|
||||||
|
mc13783_set(pmic_intm_regs[set], mask);
|
||||||
|
|
||||||
|
spi_unlock(&mc13783_spi);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t mc13783_set(unsigned address, uint32_t bits)
|
uint32_t mc13783_set(unsigned address, uint32_t bits)
|
||||||
{
|
{
|
||||||
|
|
36
firmware/target/arm/imx31/gigabeat-s/mc13783-target.h
Normal file
36
firmware/target/arm/imx31/gigabeat-s/mc13783-target.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 by Michael Sevakis
|
||||||
|
*
|
||||||
|
* Gigabeat S mc13783 event descriptions
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef MC13783_TARGET_H
|
||||||
|
#define MC13783_TARGET_H
|
||||||
|
|
||||||
|
/* Declare event indexes in priority order in a packed array */
|
||||||
|
enum mc13783_event_ids
|
||||||
|
{
|
||||||
|
MC13783_ADCDONE_EVENT = 0, /* ADC conversion complete */
|
||||||
|
MC13783_ONOFD1_EVENT, /* Power button */
|
||||||
|
#ifdef HAVE_HEADPHONE_DETECTION
|
||||||
|
MC13783_ONOFD2_EVENT, /* Headphone jack */
|
||||||
|
#endif
|
||||||
|
MC13783_CHGDET_EVENT, /* Charger detection */
|
||||||
|
MC13783_USB4V4_EVENT, /* USB insertion */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MC13783_TARGET_H */
|
|
@ -28,14 +28,11 @@
|
||||||
|
|
||||||
static bool charger_detect = false;
|
static bool charger_detect = false;
|
||||||
|
|
||||||
void power_init(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is called from the mc13783 interrupt thread */
|
/* This is called from the mc13783 interrupt thread */
|
||||||
void set_charger_inserted(bool inserted)
|
void charger_detect_event(void)
|
||||||
{
|
{
|
||||||
charger_detect = inserted;
|
charger_detect =
|
||||||
|
mc13783_read(MC13783_INTERRUPT_SENSE0) & MC13783_CHGDETS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool charger_inserted(void)
|
bool charger_inserted(void)
|
||||||
|
@ -81,6 +78,15 @@ void power_off(void)
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void power_init(void)
|
||||||
|
{
|
||||||
|
/* Poll initial state */
|
||||||
|
charger_detect_event();
|
||||||
|
|
||||||
|
/* Enable detect event */
|
||||||
|
mc13783_enable_event(MC13783_CHGDET_EVENT);
|
||||||
|
}
|
||||||
|
|
||||||
#else /* SIMULATOR */
|
#else /* SIMULATOR */
|
||||||
|
|
||||||
bool charger_inserted(void)
|
bool charger_inserted(void)
|
||||||
|
|
|
@ -19,6 +19,6 @@
|
||||||
#ifndef POWER_IMX31_H
|
#ifndef POWER_IMX31_H
|
||||||
#define POWER_IMX31_H
|
#define POWER_IMX31_H
|
||||||
|
|
||||||
void set_charger_inserted(bool inserted);
|
void charger_detect_event(void);
|
||||||
|
|
||||||
#endif /* POWER_IMX31_H */
|
#endif /* POWER_IMX31_H */
|
||||||
|
|
|
@ -48,9 +48,10 @@ static void enable_transceiver(bool enable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_set_status(bool plugged)
|
void usb_connect_event(void)
|
||||||
{
|
{
|
||||||
usb_status = plugged ? USB_INSERTED : USB_EXTRACTED;
|
uint32_t status = mc13783_read(MC13783_INTERRUPT_SENSE0);
|
||||||
|
usb_status = (status & MC13783_USB4V4S) ? USB_INSERTED : USB_EXTRACTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_detect(void)
|
int usb_detect(void)
|
||||||
|
@ -73,7 +74,11 @@ void usb_init_device(void)
|
||||||
/* Module will be turned off later after firmware init */
|
/* Module will be turned off later after firmware init */
|
||||||
usb_drv_startup();
|
usb_drv_startup();
|
||||||
|
|
||||||
mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_USB4V4M);
|
/* Initially poll */
|
||||||
|
usb_connect_event();
|
||||||
|
|
||||||
|
/* Enable PMIC event */
|
||||||
|
mc13783_enable_event(MC13783_USB4V4_EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_enable(bool on)
|
void usb_enable(bool on)
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#define USB_DRIVER_CLOSE
|
#define USB_DRIVER_CLOSE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void usb_set_status(bool plugged);
|
void usb_connect_event(void);
|
||||||
bool usb_init_device(void);
|
bool usb_init_device(void);
|
||||||
int usb_detect(void);
|
int usb_detect(void);
|
||||||
/* Read the immediate state of the cable from the PMIC */
|
/* Read the immediate state of the cable from the PMIC */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue