From b25e8bc61d8e6a708b5b6a426a71d971afb58f00 Mon Sep 17 00:00:00 2001 From: Minkyu Kang Date: Thu, 26 Aug 2010 11:34:03 +0900 Subject: [PATCH] s5pc210: support fsa9480 Signed-off-by: Minkyu Kang --- arch/arm/include/asm/arch-s5pc2xx/power.h | 32 +++++++ board/samsung/universal_c210/universal.c | 148 +++++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/arch-s5pc2xx/power.h b/arch/arm/include/asm/arch-s5pc2xx/power.h index 7d92f94..cdfb4b8 100644 --- a/arch/arm/include/asm/arch-s5pc2xx/power.h +++ b/arch/arm/include/asm/arch-s5pc2xx/power.h @@ -22,4 +22,36 @@ #ifndef __ASM_ARM_ARCH_POWER_H_ #define __ASM_ARM_ARCH_POWER_H_ +#ifndef __ASSEMBLY__ +enum reset_status { + EXTRESET, + WARMRESET, + WDTRESET, + SWRESET, +}; + +#define RESET_SW (0x1 << 29) +#define RESET_WARM (0x1 << 28) +#define RESET_WDT (0x1 << 20) +#define RESET_PIN (0x1 << 16) + +static int get_reset_status(void) +{ + unsigned int val; + + val = readl(S5PC210_POWER_BASE + 0x404); + + if (val & RESET_SW) + return SWRESET; + else if (val & RESET_WARM) + return WARMRESET; + else if (val & RESET_WDT) + return WDTRESET; + else if (val & RESET_PIN) + return EXTRESET; + + return -1; +} +#endif + #endif diff --git a/board/samsung/universal_c210/universal.c b/board/samsung/universal_c210/universal.c index ded9e00..5ca0add 100644 --- a/board/samsung/universal_c210/universal.c +++ b/board/samsung/universal_c210/universal.c @@ -26,10 +26,11 @@ #include #include #include -#include #include +#include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -143,6 +144,7 @@ static struct i2c_gpio_bus i2c_gpio[] = { }; static void check_battery(int mode); +static void check_micro_usb(int intr); void i2c_init_board(void) { @@ -164,6 +166,8 @@ void i2c_init_board(void) i2c_gpio_init(i2c_gpio, num_bus, I2C_5); + /* Reset on fsa9480 early */ + check_micro_usb(1); /* Reset on max17040 early */ if (battery_soc == 0) check_battery(1); @@ -271,6 +275,111 @@ static void check_battery(int mode) } } +static int fsa9480_probe(void) +{ + unsigned char addr = 0x25; + + i2c_set_bus_num(I2C_10); + + if (i2c_probe(addr)) { + puts("Can't found fsa9480\n"); + return 1; + } + + return 0; +} + +static void check_micro_usb(int intr) +{ + unsigned char addr; + unsigned char val[2]; + static int started_charging_once = 0; + char *path; + + if (fsa9480_probe()) + return; + + addr = 0x25; /* fsa9480 */ + + /* Clear Interrupt */ + if (intr) { + i2c_read(addr, 0x03, 1, val, 2); + return; + } + + /* Read Device Type 1 */ + i2c_read(addr, 0x0a, 1, val, 1); + +#define FSA_DEV1_CHARGER (1 << 6) +#define FSA_DEV1_UART (1 << 3) +#define FSA_DEV1_USB (1 << 2) +#define FSA_DEV2_JIG_USB_OFF (1 << 1) +#define FSA_DEV2_JIG_USB_ON (1 << 0) + +#if 0 + /* disable the charger related feature */ + /* + * If USB, use default 475mA + * If Charger, use 600mA and go to charge mode + */ + if ((val[0] & FSA_DEV1_CHARGER) && !started_charging_once) { + started_charging_once = 1; + + /* If it's full, do not charge. */ + if (battery_soc < 100) + into_charge_mode(); + else + charger_en(0); + } else if (val[0] & FSA_DEV1_USB) { + if (battery_soc < 100) + charger_en(475); /* enable charger and keep booting */ + else + charger_en(0); + } +#endif + + /* If reset status is watchdog reset then skip it */ + if (get_reset_status() != WDTRESET) { + /* If Factory Mode is Boot ON-USB, go to download mode */ + i2c_read(addr, 0x07, 1, val, 1); + +#define FSA_ADC_FAC_USB_OFF 0x18 +#define FSA_ADC_FAC_USB_ON 0x19 +#define FSA_ADC_FAC_UART 0x1d + + if (val[0] == FSA_ADC_FAC_USB_ON || + val[0] == FSA_ADC_FAC_USB_OFF) + setenv("bootcmd", "usbdown"); + } + + path = getenv("usb"); + + if (!strncmp(path, "cp", 2)) + run_command("microusb cp", 0); +} + +static void micro_usb_switch(int path) +{ + unsigned char addr; + unsigned char val[2]; + + if (fsa9480_probe()) + return; + + addr = 0x25; /* fsa9480 */ + + if (path) + val[0] = 0x90; /* VAUDIO */ + else + val[0] = (1 << 5) | (1 << 2); /* DHOST */ + + i2c_write(addr, 0x13, 1, val, 1); /* MANSW1 */ + + i2c_read(addr, 0x2, 1, val, 1); + val[0] &= ~(1 << 2); /* Manual switching */ + i2c_write(addr, 0x2, 1, val, 1); +} + #define LP3974_REG_ONOFF1 0x11 #define LP3974_REG_ONOFF2 0x12 #define LP3974_REG_ONOFF3 0x13 @@ -671,6 +780,9 @@ int misc_init_r(void) /* check max17040 */ check_battery(0); + /* check fsa9480 */ + check_micro_usb(0); + return 0; } #endif @@ -898,3 +1010,37 @@ U_BOOT_CMD( ); #endif +#ifdef CONFIG_CMD_DEVICE_POWER +static int do_microusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + switch (argc) { + case 2: + if (strncmp(argv[1], "cp", 2) == 0) { + micro_usb_switch(1); + pmic_ldo_control(0, 0, 2, 1); + setenv("usb", "cp"); + } else if (strncmp(argv[1], "ap", 2) == 0) { + micro_usb_switch(0); + pmic_ldo_control(0, 0, 2, 0); + setenv("usb", "ap"); + } + break; + default: + cmd_usage(cmdtp); + return 1; + } + + saveenv(); + + printf("USB Path is set to %s\n", getenv("usb")); + + return 0; +} + +U_BOOT_CMD( + microusb, CONFIG_SYS_MAXARGS, 1, do_microusb, + "Micro USB Switch", + "cp - switch to CP\n" + "microusb ap - switch to AP\n" +); +#endif -- 2.7.4