From 2220a4b695f2f5ac9fe212de4bcfa5365318136f Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Sat, 28 Jan 2017 14:43:35 -0500 Subject: Improve imx31 interrupt code for PMIC and GPIO Fix stuff that was bugging me about the way I did it at first. While messing around I found RDS code wasn't masking its GPIO ISR as it should, which might lead to two different interrupts messing with the static data. Change-Id: I54626809ea3039a842af0cc9e3e42853326c4193 --- .../target/arm/imx31/gigabeat-s/adc-gigabeat-s.c | 4 +- firmware/target/arm/imx31/gigabeat-s/adc-target.h | 1 - .../arm/imx31/gigabeat-s/button-gigabeat-s.c | 8 +- .../target/arm/imx31/gigabeat-s/button-target.h | 2 - .../arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c | 41 ++++++----- .../target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c | 52 ------------- firmware/target/arm/imx31/gigabeat-s/gpio-target.h | 51 +++++++------ .../arm/imx31/gigabeat-s/headphone-gigabeat-s.c | 5 +- .../arm/imx31/gigabeat-s/mc13783-gigabeat-s.c | 86 ---------------------- .../target/arm/imx31/gigabeat-s/mc13783-target.h | 44 ++++++++--- .../target/arm/imx31/gigabeat-s/power-gigabeat-s.c | 6 +- .../target/arm/imx31/gigabeat-s/power-gigabeat-s.h | 1 - .../target/arm/imx31/gigabeat-s/usb-gigabeat-s.c | 6 +- 13 files changed, 96 insertions(+), 211 deletions(-) delete mode 100644 firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c delete mode 100644 firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c (limited to 'firmware/target/arm/imx31/gigabeat-s') diff --git a/firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c index b46fc2f63f..2a89a82e46 100644 --- a/firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c @@ -111,7 +111,7 @@ bool adc_enable_channel(int channel, bool enable) } /* ADC conversion complete event - called from PMIC ISR */ -void adc_done(void) +void MC13783_EVENT_CB_ADCDONE(void) { semaphore_release(&adc_done_signal); } @@ -132,5 +132,5 @@ void adc_init(void) /* Enable ADCDONE event */ mc13783_write(MC13783_INTERRUPT_STATUS0, MC13783_ADCDONEI); - mc13783_enable_event(MC13783_ADCDONE_EVENT, true); + mc13783_enable_event(MC13783_INT_ID_ADCDONE, true); } diff --git a/firmware/target/arm/imx31/gigabeat-s/adc-target.h b/firmware/target/arm/imx31/gigabeat-s/adc-target.h index 00027e05df..dbca920b26 100644 --- a/firmware/target/arm/imx31/gigabeat-s/adc-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/adc-target.h @@ -46,7 +46,6 @@ #define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */ #define ADC_READ_ERROR 0xFFFF -void adc_done(void); /* Enable conversion of specified channel (if switchoff is possible) */ bool adc_enable_channel(int channel, bool enable); diff --git a/firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c index 3972e5722f..cdd6da041b 100644 --- a/firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c @@ -157,9 +157,9 @@ static void power_button_update(bool pressed) } /* Power button event - called from PMIC ISR */ -void button_power_event(void) +void MC13783_EVENT_CB_ONOFD1(void) { - power_button_update(!mc13783_event_sense(MC13783_ONOFD1_EVENT)); + power_button_update(!mc13783_event_sense()); } void button_init_device(void) @@ -197,7 +197,7 @@ void button_init_device(void) power_button_update(!(mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD1S)); - mc13783_enable_event(MC13783_ONOFD1_EVENT, true); + mc13783_enable_event(MC13783_INT_ID_ONOFD1, true); #ifdef HAVE_HEADPHONE_DETECTION headphone_init(); @@ -213,7 +213,7 @@ void button_close_device(void) /* Assumes HP detection is not available */ initialized = false; - mc13783_enable_event(MC13783_ONOFD1_EVENT, false); + mc13783_enable_event(MC13783_INT_ID_ONOFD1, false); ext_btn = BUTTON_NONE; } #endif /* BUTTON_DRIVER_CLOSE */ diff --git a/firmware/target/arm/imx31/gigabeat-s/button-target.h b/firmware/target/arm/imx31/gigabeat-s/button-target.h index ce624ed6cc..fba02d5dd2 100644 --- a/firmware/target/arm/imx31/gigabeat-s/button-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/button-target.h @@ -30,8 +30,6 @@ #endif void button_close_device(void); -void button_power_event(void); -void headphone_detect_event(void); void headphone_init(void); void button_headphone_set(int button); diff --git a/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c index 108a6d0944..ee91b99c0f 100644 --- a/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c @@ -26,7 +26,7 @@ #include "thread.h" #include "mc13783.h" #include "iomuxc-imx31.h" -#include "gpio-imx31.h" +#include "gpio-target.h" #include "i2c-imx31.h" #include "fmradio_i2c.h" #include "rds.h" @@ -139,20 +139,25 @@ static struct si4700_i2c_transfer_desc .xfer = { .node = &si4700_i2c_node } }; +static bool int_restore; + static void si4700_rds_read_raw_callback(struct i2c_transfer_desc *xfer) { struct si4700_i2c_transfer_desc *xf = (struct si4700_i2c_transfer_desc *)xfer; - if (xfer->rxcount != 0) - return; /* Read didn't finish */ - - uint16_t rds_data[4]; + if (xfer->rxcount == 0) + { + uint16_t rds_data[4]; + si4700_rds_read_raw_async_complete(xf->regbuf, rds_data); - si4700_rds_read_raw_async_complete(xf->regbuf, rds_data); + if (rds_process(rds_data)) + si4700_rds_set_event(); + } + /* else read didn't finish */ - if (rds_process(rds_data)) - si4700_rds_set_event(); + if (int_restore) + gpio_int_enable(SI4700_EVENT_ID); } /* Callback from si4700_rds_read_raw to execute the read */ @@ -169,10 +174,13 @@ void si4700_read_raw_async(int count) } /* RDS GPIO interrupt handler - start RDS data read */ -void si4700_stc_rds_event(void) +void INT_SI4700_RDS(void) { - /* read and clear the interrupt */ - SI4700_GPIO_STC_RDS_ISR = (1ul << SI4700_GPIO_STC_RDS_LINE); + /* mask and clear the interrupt */ + gpio_int_disable(SI4700_EVENT_ID); + gpio_int_clear(SI4700_EVENT_ID); + + /* read the RDS data */ si4700_rds_read_raw_async(); } @@ -180,13 +188,10 @@ void si4700_stc_rds_event(void) powering down */ void si4700_rds_powerup(bool on) { - gpio_disable_event(SI4700_STC_RDS_EVENT_ID); - - if (on) - { - SI4700_GPIO_STC_RDS_ISR = (1ul << SI4700_GPIO_STC_RDS_LINE); - gpio_enable_event(SI4700_STC_RDS_EVENT_ID); - } + int_restore = on; + gpio_int_disable(SI4700_EVENT_ID); + gpio_int_clear(SI4700_EVENT_ID); + gpio_enable_event(SI4700_EVENT_ID, on); } /* One-time RDS init at startup */ diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c deleted file mode 100644 index 51446934aa..0000000000 --- a/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (c) 2008 by Michael Sevakis - * - * Gigabeat S GPIO interrupt event descriptions - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "system.h" -#include "avic-imx31.h" -#include "gpio-imx31.h" - -/* Gigabeat S definitions for static GPIO event registration */ - -/* Describes single events for each GPIO1 pin */ -const struct gpio_event gpio1_events[] = -{ - /* mc13783 keeps the PRIINT high (no low pulse) if other unmasked - * interrupts become active when clearing them or if a source being - * cleared becomes active at that time. Edge-detection will not get - * a rising edge in that case so use high-level sense. */ - [MC13783_EVENT_ID-GPIO1_EVENT_FIRST] = - { - .mask = 1 << MC13783_GPIO_LINE, - .sense = GPIO_SENSE_HIGH_LEVEL, - .callback = mc13783_event, - }, -#ifndef BOOTLOADER - /* Generates a 5ms low pulse on the line - detect the falling edge */ - [SI4700_STC_RDS_EVENT_ID] = - { - .mask = 1 << SI4700_GPIO_STC_RDS_LINE, - .sense = GPIO_SENSE_FALLING, - .callback = si4700_stc_rds_event, - }, -#endif -}; diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-target.h b/firmware/target/arm/imx31/gigabeat-s/gpio-target.h index 4903d0f631..543b25f244 100644 --- a/firmware/target/arm/imx31/gigabeat-s/gpio-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/gpio-target.h @@ -23,34 +23,33 @@ #ifndef GPIO_TARGET_H #define GPIO_TARGET_H -/* MC13783 GPIO pin info for this target */ -#define MC13783_GPIO_IMR GPIO1_IMR -#define MC13783_GPIO_NUM GPIO1_NUM -#define MC13783_GPIO_ISR GPIO1_ISR -#define MC13783_GPIO_LINE 31 - -/* SI4700 GPIO STC/RDS pin info for this target */ -#define SI4700_GPIO_STC_RDS_IMR GPIO1_IMR -#define SI4700_GPIO_STC_RDS_NUM GPIO1_NUM -#define SI4700_GPIO_STC_RDS_ISR GPIO1_ISR -#define SI4700_GPIO_STC_RDS_LINE 27 +/* Gigabeat S definitions for static GPIO event registration */ +#include "gpio-imx31.h" + +#ifdef DEFINE_GPIO_VECTOR_TABLE + +GPIO_VECTOR_TBL_START() + /* mc13783 keeps the PRIINT high (no low pulse) if other unmasked + * interrupts become active when clearing them or if a source being + * cleared becomes active at that time. Edge-detection will not get + * a rising edge in that case so use high-level sense. */ + GPIO_EVENT_VECTOR(GPIO1_31, GPIO_SENSE_HIGH_LEVEL) +#if CONFIG_TUNER + /* Generates a 5ms low pulse on the line - detect the falling edge */ + GPIO_EVENT_VECTOR(GPIO1_27, GPIO_SENSE_FALLING) +#endif /* CONFIG_TUNER */ +GPIO_VECTOR_TBL_END() #define GPIO1_INT_PRIO INT_PRIO_DEFAULT -/* Declare event indexes in priority order in a packed array */ -enum gpio_event_ids -{ - /* GPIO1 event IDs */ - MC13783_EVENT_ID = GPIO1_EVENT_FIRST, - SI4700_STC_RDS_EVENT_ID, - GPIO1_NUM_EVENTS = 2, - /* GPIO2 event IDs */ - /* none defined */ - /* GPIO3 event IDs */ - /* none defined */ -}; - -void mc13783_event(void); -void si4700_stc_rds_event(void); +#endif /* DEFINE_GPIO_VECTOR_TABLE */ + +#define INT_MC13783 GPIO1_31_EVENT_CB +#define MC13783_EVENT_ID GPIO1_31_ID + +#if CONFIG_TUNER +#define INT_SI4700_RDS GPIO1_27_EVENT_CB +#define SI4700_EVENT_ID GPIO1_27_ID +#endif /* CONFIG_TUNER */ #endif /* GPIO_TARGET_H */ diff --git a/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c index 6fdde32185..cf0a378fc7 100644 --- a/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c @@ -25,7 +25,6 @@ #include "kernel.h" #include "thread.h" #include "mc13783.h" -#include "mc13783-target.h" #include "adc.h" #include "button.h" @@ -146,7 +145,7 @@ static void NORETURN_ATTR headphone_thread(void) } /* HP plugged/unplugged event - called from PMIC ISR */ -void headphone_detect_event(void) +void MC13783_EVENT_CB_ONOFD2(void) { /* Trigger the thread immediately. */ semaphore_release(&headphone_wakeup); @@ -170,5 +169,5 @@ void INIT_ATTR headphone_init(void) IF_COP(, CPU)); /* Enable PMIC event */ - mc13783_enable_event(MC13783_ONOFD2_EVENT, true); + mc13783_enable_event(MC13783_INT_ID_ONOFD2, true); } diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c deleted file mode 100644 index 76001dddd6..0000000000 --- a/firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c +++ /dev/null @@ -1,86 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (c) 2008 by Michael Sevakis - * - * Gigabeat S MC13783 event descriptions - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "system.h" -#include "spi-imx31.h" -#include "mc13783.h" -#include "mc13783-target.h" -#include "adc-target.h" -#include "button-target.h" -#include "power-gigabeat-s.h" -#include "powermgmt-target.h" - -/* Gigabeat S mc13783 serial interface node. */ - -struct spi_node mc13783_spi = -{ - /* Based upon original firmware settings */ - CSPI2_NUM, /* CSPI module 2 */ - CSPI_CONREG_CHIP_SELECT_SS0 | /* Chip select 0 */ - CSPI_CONREG_DRCTL_DONT_CARE | /* Don't care about CSPI_RDY */ - CSPI_CONREG_DATA_RATE_DIV_32 | /* Clock = IPG_CLK/32 = 2,062,500Hz. */ - CSPI_BITCOUNT(32-1) | /* All 32 bits are to be transferred */ - CSPI_CONREG_SSPOL | /* SS active high */ - CSPI_CONREG_SSCTL | /* Negate SS between SPI bursts */ - CSPI_CONREG_MODE, /* Master mode */ - 0, /* SPI clock - no wait states */ -}; - - -/* Gigabeat S definitions for static MC13783 event registration */ - -const struct mc13783_event mc13783_events[MC13783_NUM_EVENTS] = -{ - [MC13783_ADCDONE_EVENT] = /* ADC conversion complete */ - { - .int_id = MC13783_INT_ID_ADCDONE, - .sense = 0, - .callback = adc_done, - }, - [MC13783_ONOFD1_EVENT] = /* Power button */ - { - .int_id = MC13783_INT_ID_ONOFD1, - .sense = MC13783_ONOFD1S, - .callback = button_power_event, - }, - [MC13783_SE1_EVENT] = /* Main charger detection */ - { - .int_id = MC13783_INT_ID_SE1, - .sense = MC13783_SE1S, - .callback = charger_main_detect_event, - }, - [MC13783_USB_EVENT] = /* USB insertion/USB charger detection */ - { - .int_id = MC13783_INT_ID_USB, - .sense = MC13783_USB4V4S, - .callback = usb_connect_event, - }, -#ifdef HAVE_HEADPHONE_DETECTION - [MC13783_ONOFD2_EVENT] = /* Headphone jack */ - { - .int_id = MC13783_INT_ID_ONOFD2, - .sense = 0, - .callback = headphone_detect_event, - }, -#endif -}; diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h b/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h index 48d634035a..179c65cad6 100644 --- a/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h @@ -23,17 +23,41 @@ #ifndef MC13783_TARGET_H #define MC13783_TARGET_H -/* Declare event indexes in priority order in a packed array */ -enum mc13783_event_ids +#include "mc13783.h" + +#ifdef DEFINE_MC13783_VECTOR_TABLE + +/* Gigabeat S mc13783 serial interface node. */ +static struct spi_node mc13783_spi = { - MC13783_ADCDONE_EVENT = 0, /* ADC conversion complete */ - MC13783_ONOFD1_EVENT, /* Power button */ -#ifdef HAVE_HEADPHONE_DETECTION - MC13783_ONOFD2_EVENT, /* Headphone jack */ -#endif - MC13783_SE1_EVENT, /* Main charger detection */ - MC13783_USB_EVENT, /* USB insertion */ - MC13783_NUM_EVENTS, + /* Based upon original firmware settings */ + CSPI2_NUM, /* CSPI module 2 */ + CSPI_CONREG_CHIP_SELECT_SS0 | /* Chip select 0 */ + CSPI_CONREG_DRCTL_DONT_CARE | /* Don't care about CSPI_RDY */ + CSPI_CONREG_DATA_RATE_DIV_32 | /* Clock = IPG_CLK/32 = 2,062,500Hz. */ + CSPI_BITCOUNT(32-1) | /* All 32 bits are to be transferred */ + CSPI_CONREG_SSPOL | /* SS active high */ + CSPI_CONREG_SSCTL | /* Negate SS between SPI bursts */ + CSPI_CONREG_MODE, /* Master mode */ + 0, /* SPI clock - no wait states */ }; +/* Gigabeat S definitions for static MC13783 event registration */ +MC13783_EVENT_VECTOR_TBL_START() + /* ADC conversion complete */ + MC13783_EVENT_VECTOR(ADCDONE, 0) + /* Power button */ + MC13783_EVENT_VECTOR(ONOFD1, MC13783_ONOFD1S) + /* Main charger detection */ + MC13783_EVENT_VECTOR(SE1, MC13783_SE1S) + /* USB insertion/USB charger detection */ + MC13783_EVENT_VECTOR(USB, MC13783_USB4V4S) +#ifdef HAVE_HEADPHONE_DETECTION + /* Headphone jack */ + MC13783_EVENT_VECTOR(ONOFD2, 0) +#endif /* HAVE_HEADPHONE_DETECTION */ +MC13783_EVENT_VECTOR_TBL_END() + +#endif /* DEFINE_MC13783_VECTOR_TABLE */ + #endif /* MC13783_TARGET_H */ diff --git a/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c index 5d89802bc9..81f150acd7 100644 --- a/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c @@ -66,9 +66,9 @@ static void update_main_charger(bool present) } /* Detect changes in presence of the AC adaptor. Called from PMIC ISR. */ -void charger_main_detect_event(void) +void MC13783_EVENT_CB_SE1(void) { - update_main_charger(mc13783_event_sense(MC13783_SE1_EVENT)); + update_main_charger(mc13783_event_sense()); } /* Detect changes in USB bus power. Called from usb connect event ISR. */ @@ -159,5 +159,5 @@ void power_init(void) & MC13783_SE1S); /* Enable detect event */ - mc13783_enable_event(MC13783_SE1_EVENT, true); + mc13783_enable_event(MC13783_INT_ID_SE1, true); } diff --git a/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.h b/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.h index 9294de102c..2cd509267c 100644 --- a/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.h +++ b/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.h @@ -21,7 +21,6 @@ #ifndef POWER_IMX31_H #define POWER_IMX31_H -void charger_main_detect_event(void); void charger_usb_detect_event(int status); #endif /* POWER_IMX31_H */ diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c index 9129568b7a..71e8342595 100644 --- a/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c @@ -70,10 +70,10 @@ static void update_usb_status(bool sense) } /* Detect presence of USB bus - called from PMIC ISR */ -void usb_connect_event(void) +void MC13783_EVENT_CB_USB(void) { /* Read the associated sense value */ - update_usb_status(mc13783_event_sense(MC13783_USB_EVENT)); + update_usb_status(mc13783_event_sense()); } int usb_detect(void) @@ -90,7 +90,7 @@ void usb_init_device(void) update_usb_status(usb_plugged()); /* Enable PMIC event */ - mc13783_enable_event(MC13783_USB_EVENT, true); + mc13783_enable_event(MC13783_INT_ID_USB, true); } void usb_enable(bool on) -- cgit v1.2.3