diff options
Diffstat (limited to 'u-boot/board/goldelico/gta04/status.c')
-rw-r--r-- | u-boot/board/goldelico/gta04/status.c | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/u-boot/board/goldelico/gta04/status.c b/u-boot/board/goldelico/gta04/status.c new file mode 100644 index 0000000..aebd95e --- /dev/null +++ b/u-boot/board/goldelico/gta04/status.c @@ -0,0 +1,289 @@ +/* u-boot driver for the GTA04 LEDs and Buttons + * + * Copyright (C) 2010 by Golden Delicious Computers GmbH&Co. KG + * Author: H. Nikolaus Schaller <hns@goldelico.com> + * All rights reserved. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <common.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/mux.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/gpio.h> +#include <asm/mach-types.h> +#include <i2c.h> +#include <twl4030.h> +#include "status.h" + +#if defined(CONFIG_OMAP3_GTA04) + +// no need to probe for LED controller (compiler should optimize unnecessary code) +#define hasTCA6507 (1==1) + +#else + +static int hasTCA6507=0; + +#endif + +#define TWL4030_I2C_BUS (1-1) // I2C1 +#define TCA6507_BUS (2-1) // I2C2 +#define TCA6507_ADDRESS 0x45 + +/* register numbers */ +#define TCA6507_SELECT0 0 +#define TCA6507_SELECT1 1 +#define TCA6507_SELECT2 2 +#define TCA6507_FADE_ON_TIME 3 +#define TCA6507_FULLY_ON_TIME 4 +#define TCA6507_FADR_OFF_TIME 5 +#define TCA6507_FIRST_FULLY_OFF_TIME 6 +#define TCA6507_SECOND_FULLY_OFF_TIME 7 +#define TCA6507_MAXIMUM_INTENSITY 8 +#define TCA6507_ONE_SHOT_MASTER_INTENSITY 9 +#define TCA6507_INITIALIZATION 10 + +#define TCA6507_AUTO_INCREMENT 16 + +// we can't include "beagle.h" +/* BeagleBoard revisions */ +extern int get_board_revision(void); +#define REVISION_AXBX 0x7 +#define REVISION_CX 0x6 +#define REVISION_C4 0x5 +#define REVISION_XM 0x0 + +static int isXM = 0; + +#if defined(CONFIG_OMAP3_GTA04) + +#define GPIO_AUX 7 // AUX/User button +#define GPIO_POWER -1 // N/A on GTA04 (access through TPS65950) +#define GPIO_GPSEXT 144 // external GPS antenna is plugged in +#define GPIO_PENIRQ 160 // TSC must be set up to provide PENIRQ + +#elif defined(CONFIG_OMAP3_BEAGLE_HYBRID) + +#define GPIO_AUX 136 // AUX/User button +#define GPIO_POWER 137 // POWER button +#define GPIO_GPSEXT 138 // external GPS antenna is plugged in +#define GPIO_PENIRQ 157 // TSC must be set up to provide PENIRQ + +#elif defined(CONFIG_OMAP3_BEAGLE_EXPANDER) + +#define GPIO_AUX 136 // AUX/User button +#define GPIO_POWER 137 // POWER button +#define GPIO_GPSEXT 138 // external GPS antenna is plugged in +#define GPIO_PENIRQ 157 // TSC must be set up to provide PENIRQ + +#else + +#error unknown config + +#endif + +#define GPIO_LED_AUX_RED (isXM?88:70) // AUX +#define GPIO_LED_AUX_GREEN (isXM?89:71) // AUX +#define GPIO_LED_POWER_RED 78 // Power +#define GPIO_LED_POWER_GREEN 79 // Power +#define GPIO_LED_VIBRA (isXM?2:88) // Vibracall motor +#define GPIO_LED_UNUSED (isXM?3:89) // unused + +static int status; + +void status_set_status(int value) +{ + status=value; + if(!hasTCA6507) { + omap_set_gpio_dataout(GPIO_LED_AUX_RED, (value&(1 << 0))); + omap_set_gpio_dataout(GPIO_LED_AUX_GREEN, (value&(1 << 1))); + omap_set_gpio_dataout(GPIO_LED_POWER_RED, (value&(1 << 3))); + omap_set_gpio_dataout(GPIO_LED_POWER_GREEN, (value&(1 << 4))); + omap_set_gpio_dataout(GPIO_LED_VIBRA, (value&(1 << 6))); + omap_set_gpio_dataout(GPIO_LED_UNUSED, (value&(1 << 7))); + } + else { + value &= 0x3f; // 6 LEDs only - 7th is reserved to reset the WLAN/BT chip + i2c_set_bus_num(TCA6507_BUS); // write I2C2 + // we could write a autoincrement address and all 3 bytes in a single message + // we could set the TCA to do smooth transitions + i2c_reg_write(TCA6507_ADDRESS, TCA6507_SELECT0, 0); + i2c_reg_write(TCA6507_ADDRESS, TCA6507_SELECT1, 0); + i2c_reg_write(TCA6507_ADDRESS, TCA6507_SELECT2, value); // 1 = on + } +} + +int status_get_buttons(void) +{ // convert button state into led state +#if defined(CONFIG_OMAP3_GTA04) + u8 val; + i2c_set_bus_num(TWL4030_I2C_BUS); // read I2C1 + twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, &val, TWL4030_PM_MASTER_STS_HW_CONDITIONS); // read state of power button (bit 0) from TPS65950 + return ((omap_get_gpio_datain(GPIO_AUX)) << 0) | + ((omap_get_gpio_datain(GPIO_GPSEXT)) << 1) | + (((val&0x01) != 0) << 3) | + ((omap_get_gpio_datain(GPIO_PENIRQ)) << 4); +#elif defined(CONFIG_OMAP3_BEAGLE_EXPANDER) + return + ((omap_get_gpio_datain(GPIO_AUX)) << 0) | + ((0) << 1) | + ((!omap_get_gpio_datain(GPIO_POWER)) << 3) | + ((omap_get_gpio_datain(GPIO_PENIRQ)) << 4); +#else + return + ((!omap_get_gpio_datain(GPIO_AUX)) << 0) | + ((omap_get_gpio_datain(GPIO_GPSEXT)) << 1) | + ((!omap_get_gpio_datain(GPIO_POWER)) << 3) | + ((omap_get_gpio_datain(GPIO_PENIRQ)) << 4); +#endif +} + +int status_init(void) +{ + isXM = (get_board_revision() == REVISION_XM); +#if !defined(CONFIG_OMAP3_GTA04) + if(i2c_set_bus_num(TCA6507_BUS)) + { + printf ("could not select I2C2\n"); + return 1; + } + hasTCA6507 = !i2c_probe(TCA6507_ADDRESS); +#endif + + if(!hasTCA6507) { + if(isXM) { // XM has scrambled dss assignment with respect to default ball name + MUX_VAL(CP(DSS_DATA18), (IEN | PTD | EN | M4)); /*GPIO */ + MUX_VAL(CP(DSS_DATA19), (IEN | PTD | EN | M4)); /*GPIO */ + MUX_VAL(CP(DSS_DATA8), (IEN | PTD | EN | M4)); /*GPIO */ + MUX_VAL(CP(DSS_DATA9), (IEN | PTD | EN | M4)); /*GPIO */ + MUX_VAL(CP(SYS_BOOT0), (IEN | PTD | EN | M4)); /*GPIO */ + MUX_VAL(CP(SYS_BOOT1), (IEN | PTD | EN | M4)); /*GPIO */ + } + else { + MUX_VAL(CP(DSS_DATA0), (IEN | PTD | EN | M4)); /*GPIO */ + MUX_VAL(CP(DSS_DATA1), (IEN | PTD | EN | M4)); /*GPIO */ + MUX_VAL(CP(DSS_DATA8), (IEN | PTD | EN | M4)); /*GPIO */ + MUX_VAL(CP(DSS_DATA9), (IEN | PTD | EN | M4)); /*GPIO */ + MUX_VAL(CP(DSS_DATA16), (IEN | PTD | EN | M4)); /*GPIO */ + MUX_VAL(CP(DSS_DATA17), (IEN | PTD | EN | M4)); /*GPIO */ + } + + omap_request_gpio(GPIO_LED_AUX_GREEN); + omap_request_gpio(GPIO_LED_AUX_RED); + omap_request_gpio(GPIO_LED_POWER_GREEN); + omap_request_gpio(GPIO_LED_POWER_RED); + omap_request_gpio(GPIO_LED_VIBRA); + omap_request_gpio(GPIO_LED_UNUSED); + omap_request_gpio(GPIO_POWER); + } + else { + // initialize I2C controller + } + + omap_request_gpio(GPIO_AUX); + omap_request_gpio(GPIO_GPSEXT); + omap_request_gpio(GPIO_PENIRQ); + + if(!hasTCA6507) { + omap_set_gpio_direction(GPIO_LED_AUX_GREEN, 0); // output + omap_set_gpio_direction(GPIO_LED_AUX_RED, 0); // output + omap_set_gpio_direction(GPIO_LED_POWER_GREEN, 0); // output + omap_set_gpio_direction(GPIO_LED_POWER_RED, 0); // output + omap_set_gpio_direction(GPIO_LED_VIBRA, 0); // output + omap_set_gpio_direction(GPIO_LED_UNUSED, 0); // output + omap_set_gpio_direction(GPIO_POWER, 1); // input + } + + omap_set_gpio_direction(GPIO_AUX, 1); // input +#ifndef CONFIG_OMAP3_GTA04 + omap_set_gpio_direction(GPIO_POWER, 1); // input +#endif + omap_set_gpio_direction(GPIO_GPSEXT, 1); // input + + // when sould we do omap_free_gpio(GPIO_LED_AUX_GREEN); ? + printf("did init LED driver for %s\n", hasTCA6507?"TCA6507":"GPIOs"); + + return 0; +} + +int status_set_flash (int mode) +{ // 0: off, 1: torch, 2: flash + if(i2c_set_bus_num(TCA6507_BUS)) + { + printf ("could not select I2C2\n"); + return 1; + } + // initialize if needed + // set flash controller mode + return 0; +} + +int status_set_vibra (int value) +{ // 0: off otherwise msb controls left/right (2's complement) + unsigned char byte; + if(i2c_set_bus_num(TWL4030_I2C_BUS)) + { + printf ("could not select I2C1\n"); + return 1; + } + + // program Audio controller (see document SWCU050D) + + byte = 0x00; // LEDAON=LEDBON=0 + i2c_write(0x4A, 0xEE, 1, &byte, 1); // LEDEN + byte = value != 0 ? 0x03 : 0x00; // 8 kHz, Codec on (if value != 0), Option 1:RX and TX stereo audio path + i2c_write(0x49, 0x01, 1, &byte, 1); // CODEC_MODE + byte = 0x16; // APLL_EN enabled, 26 MHz + i2c_write(0x49, 0x3a, 1, &byte, 1); // APLL_CTL + byte = 0x04; // use PWM + i2c_write(0x4B, 0x60, 1, &byte, 1); // VIBRATOR_CFG + byte = value > 0?0x01:0x03; // use VIBRADIR, local driver, enable + i2c_write(0x49, 0x45, 1, &byte, 1); // VIBRATOR_CFG + byte = 256-(value>=0?value:-value); // PWM turnon value + if(byte == 0) byte = 0x01; // 0x00 is forbidden! + i2c_write(0x49, 0x46, 1, &byte, 1); // VIBRA_SEL + + // do we have to set some Audio PLL frequency (number 6 & 7?) + + /* + To use the vibrator H-bridge: + 1. Disable LEDA: Set the LEDEN[0]LEDAON bit to logic 0. + 2. Disable LEDB: Set the LEDEN[1]LEDBON bit to logic 0. + 3. Turn on the codec: + Set the CODEC_MODE[1] CODECPDZ bit to 1. + The H-bridge vibrator can get its operation from the following sources: + • An audio channel can provide the stimulus. + • A PWM in the audio subchip can generate the signal. + If an audio channel provides the motivating force for the vibrator (for example: the audio right 1 channel): + 1. Set the VIBR_CTL[4]VIBRA_SEL bit to 1. + 2. Set the VIBR_CTL[5]VIBRA_DIR_SEL bit to 1. + 3. Set the VIBR_CTL[3:2]VIBRA_AUDIO_SEL bit field to 0x1 (audio right 1 channel). + 4. Select the use of the SIGN bit to determine the output phase to VIBRA_P and VIBRA_M. + 5. Set the VIBRA_CTL[0]VIBRA_EN bit to 1 (power to the H-bridge is driven by audiodata). + Notes: + • If audio data drives the vibrator H-bridge, set the VIBRA_SET register to 0xFF. + • The direction of the vibrator H-bridge controlled by the VIBRA_DIR bit can be changed + on the fly. + 6. Set the audio PLL input frequency: The APLL_CTL APLL_INFREQ bitfield=0x6. + 7. Enable the audio PLL: The APLL_CTL APLL_ENbit=1. + Note: Do not enable LEDA/B and the H-vibrator simultaneously. + */ + return 0; +} |