X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=arch%2Farm%2Fmach-pxa%2Fmagician.c;h=e81dd0c8e40dcced02770cb7dc57c4ca4634102b;hb=75047944480a33afad76a272b21116d032ba61fa;hp=9e126a90113709512a26ca670a1384e19677980e;hpb=60802188ece1c5b63deefc05b7b442625e575476;p=safe%2Fjmp%2Flinux-2.6 diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 9e126a9..e81dd0c 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -17,62 +17,144 @@ #include #include #include +#include #include #include #include -#include -#include +#include #include #include +#include +#include +#include +#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include + +#include "devices.h" #include "generic.h" +static unsigned long magician_pin_config[] __initdata = { + + /* SDRAM and Static Memory I/O Signals */ + GPIO20_nSDCS_2, + GPIO21_nSDCS_3, + GPIO15_nCS_1, + GPIO78_nCS_2, /* PASIC3 */ + GPIO79_nCS_3, /* EGPIO CPLD */ + GPIO80_nCS_4, + GPIO33_nCS_5, + + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, + + /* PWM 0 */ + GPIO16_PWM0_OUT, + + /* I2S */ + GPIO28_I2S_BITCLK_OUT, + GPIO29_I2S_SDATA_IN, + GPIO31_I2S_SYNC, + GPIO113_I2S_SYSCLK, + + /* SSP 1 */ + GPIO23_SSP1_SCLK, + GPIO24_SSP1_SFRM, + GPIO25_SSP1_TXD, + + /* SSP 2 */ + GPIO19_SSP2_SCLK, + GPIO14_SSP2_SFRM, + GPIO89_SSP2_TXD, + GPIO88_SSP2_RXD, + + /* MMC */ + GPIO32_MMC_CLK, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + GPIO112_MMC_CMD, + + /* LCD */ + GPIOxx_LCD_TFT_16BPP, + + /* QCI */ + GPIO12_CIF_DD_7, + GPIO17_CIF_DD_6, + GPIO50_CIF_DD_3, + GPIO51_CIF_DD_2, + GPIO52_CIF_DD_4, + GPIO53_CIF_MCLK, + GPIO54_CIF_PCLK, + GPIO55_CIF_DD_1, + GPIO81_CIF_DD_0, + GPIO82_CIF_DD_5, + GPIO84_CIF_FV, + GPIO85_CIF_LV, + + /* Magician specific input GPIOs */ + GPIO9_GPIO, /* unknown */ + GPIO10_GPIO, /* GSM_IRQ */ + GPIO13_GPIO, /* CPLD_IRQ */ + GPIO107_GPIO, /* DS1WM_IRQ */ + GPIO108_GPIO, /* GSM_READY */ + GPIO115_GPIO, /* nPEN_IRQ */ + + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, +}; + /* * IRDA */ -static void magician_irda_transceiver_mode(struct device *dev, int mode) -{ - gpio_set_value(GPIO83_MAGICIAN_nIR_EN, mode & IR_OFF); -} - static struct pxaficp_platform_data magician_ficp_info = { - .transceiver_cap = IR_SIRMODE | IR_OFF, - .transceiver_mode = magician_irda_transceiver_mode, + .gpio_pwdown = GPIO83_MAGICIAN_nIR_EN, + .transceiver_cap = IR_SIRMODE | IR_OFF, }; /* * GPIO Keys */ +#define INIT_KEY(_code, _gpio, _desc) \ + { \ + .code = KEY_##_code, \ + .gpio = _gpio, \ + .desc = _desc, \ + .type = EV_KEY, \ + .wakeup = 1, \ + } + static struct gpio_keys_button magician_button_table[] = { - {KEY_POWER, GPIO0_MAGICIAN_KEY_POWER, 0, "Power button"}, - {KEY_ESC, GPIO37_MAGICIAN_KEY_HANGUP, 0, "Hangup button"}, - {KEY_F10, GPIO38_MAGICIAN_KEY_CONTACTS, 0, "Contacts button"}, - {KEY_CALENDAR, GPIO90_MAGICIAN_KEY_CALENDAR, 0, "Calendar button"}, - {KEY_CAMERA, GPIO91_MAGICIAN_KEY_CAMERA, 0, "Camera button"}, - {KEY_UP, GPIO93_MAGICIAN_KEY_UP, 0, "Up button"}, - {KEY_DOWN, GPIO94_MAGICIAN_KEY_DOWN, 0, "Down button"}, - {KEY_LEFT, GPIO95_MAGICIAN_KEY_LEFT, 0, "Left button"}, - {KEY_RIGHT, GPIO96_MAGICIAN_KEY_RIGHT, 0, "Right button"}, - {KEY_KPENTER, GPIO97_MAGICIAN_KEY_ENTER, 0, "Action button"}, - {KEY_RECORD, GPIO98_MAGICIAN_KEY_RECORD, 0, "Record button"}, - {KEY_VOLUMEUP, GPIO100_MAGICIAN_KEY_VOL_UP, 0, "Volume up"}, - {KEY_VOLUMEDOWN, GPIO101_MAGICIAN_KEY_VOL_DOWN, 0, "Volume down"}, - {KEY_PHONE, GPIO102_MAGICIAN_KEY_PHONE, 0, "Phone button"}, - {KEY_PLAY, GPIO99_MAGICIAN_HEADPHONE_IN, 0, "Headset button"}, + INIT_KEY(POWER, GPIO0_MAGICIAN_KEY_POWER, "Power button"), + INIT_KEY(ESC, GPIO37_MAGICIAN_KEY_HANGUP, "Hangup button"), + INIT_KEY(F10, GPIO38_MAGICIAN_KEY_CONTACTS, "Contacts button"), + INIT_KEY(CALENDAR, GPIO90_MAGICIAN_KEY_CALENDAR, "Calendar button"), + INIT_KEY(CAMERA, GPIO91_MAGICIAN_KEY_CAMERA, "Camera button"), + INIT_KEY(UP, GPIO93_MAGICIAN_KEY_UP, "Up button"), + INIT_KEY(DOWN, GPIO94_MAGICIAN_KEY_DOWN, "Down button"), + INIT_KEY(LEFT, GPIO95_MAGICIAN_KEY_LEFT, "Left button"), + INIT_KEY(RIGHT, GPIO96_MAGICIAN_KEY_RIGHT, "Right button"), + INIT_KEY(KPENTER, GPIO97_MAGICIAN_KEY_ENTER, "Action button"), + INIT_KEY(RECORD, GPIO98_MAGICIAN_KEY_RECORD, "Record button"), + INIT_KEY(VOLUMEUP, GPIO100_MAGICIAN_KEY_VOL_UP, "Volume up"), + INIT_KEY(VOLUMEDOWN, GPIO101_MAGICIAN_KEY_VOL_DOWN, "Volume down"), + INIT_KEY(PHONE, GPIO102_MAGICIAN_KEY_PHONE, "Phone button"), + INIT_KEY(PLAY, GPIO99_MAGICIAN_HEADPHONE_IN, "Headset button"), }; static struct gpio_keys_platform_data gpio_keys_data = { @@ -98,7 +180,7 @@ static struct platform_device gpio_keys = { static struct resource egpio_resources[] = { [0] = { .start = PXA_CS3_PHYS, - .end = PXA_CS3_PHYS + 0x20, + .end = PXA_CS3_PHYS + 0x20 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -245,8 +327,7 @@ static struct pxafb_mach_info toppoly_info = { .modes = toppoly_modes, .num_modes = 1, .fixed_modes = 1, - .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - .lccr3 = LCCR3_PixRsEdg, + .lcd_conn = LCD_COLOR_TFT_16BPP, .pxafb_lcd_power = toppoly_lcd_power, }; @@ -254,8 +335,8 @@ static struct pxafb_mach_info samsung_info = { .modes = samsung_modes, .num_modes = 1, .fixed_modes = 1, - .lccr0 = LCCR0_LDDALT | LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - .lccr3 = LCCR3_PixFlEdg, + .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL |\ + LCD_ALTERNATE_MAPPING, .pxafb_lcd_power = samsung_lcd_power, }; @@ -263,81 +344,230 @@ static struct pxafb_mach_info samsung_info = { * Backlight */ -static void magician_set_bl_intensity(int intensity) +static int magician_backlight_init(struct device *dev) { - if (intensity) { - PWM_CTRL0 = 1; - PWM_PERVAL0 = 0xc8; - if (intensity > 0xc7) { - PWM_PWDUTY0 = intensity - 0x48; - gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 1); - } else { - PWM_PWDUTY0 = intensity; - gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 0); - } - gpio_set_value(EGPIO_MAGICIAN_BL_POWER, 1); - pxa_set_cken(CKEN_PWM0, 1); + int ret; + + ret = gpio_request(EGPIO_MAGICIAN_BL_POWER, "BL_POWER"); + if (ret) + goto err; + ret = gpio_request(EGPIO_MAGICIAN_BL_POWER2, "BL_POWER2"); + if (ret) + goto err2; + return 0; + +err2: + gpio_free(EGPIO_MAGICIAN_BL_POWER); +err: + return ret; +} + +static int magician_backlight_notify(struct device *dev, int brightness) +{ + gpio_set_value(EGPIO_MAGICIAN_BL_POWER, brightness); + if (brightness >= 200) { + gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 1); + return brightness - 72; } else { - /* PWM_PWDUTY0 = intensity; */ - gpio_set_value(EGPIO_MAGICIAN_BL_POWER, 0); - pxa_set_cken(CKEN_PWM0, 0); + gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 0); + return brightness; } } -static struct generic_bl_info backlight_info = { - .default_intensity = 0x64, - .limit_mask = 0x0b, - .max_intensity = 0xc7+0x48, - .set_bl_intensity = magician_set_bl_intensity, +static void magician_backlight_exit(struct device *dev) +{ + gpio_free(EGPIO_MAGICIAN_BL_POWER); + gpio_free(EGPIO_MAGICIAN_BL_POWER2); +} + +static struct platform_pwm_backlight_data backlight_data = { + .pwm_id = 0, + .max_brightness = 272, + .dft_brightness = 100, + .pwm_period_ns = 30923, + .init = magician_backlight_init, + .notify = magician_backlight_notify, + .exit = magician_backlight_exit, }; static struct platform_device backlight = { - .name = "generic-bl", + .name = "pwm-backlight", + .id = -1, .dev = { - .platform_data = &backlight_info, + .parent = &pxa27x_device_pwm0.dev, + .platform_data = &backlight_data, }, +}; + +/* + * LEDs + */ + +static struct gpio_led gpio_leds[] = { + { + .name = "magician::vibra", + .default_trigger = "none", + .gpio = GPIO22_MAGICIAN_VIBRA_EN, + }, + { + .name = "magician::phone_bl", + .default_trigger = "backlight", + .gpio = GPIO103_MAGICIAN_LED_KP, + }, +}; + +static struct gpio_led_platform_data gpio_led_info = { + .leds = gpio_leds, + .num_leds = ARRAY_SIZE(gpio_leds), +}; + +static struct platform_device leds_gpio = { + .name = "leds-gpio", .id = -1, + .dev = { + .platform_data = &gpio_led_info, + }, +}; + +static struct pasic3_led pasic3_leds[] = { + { + .led = { + .name = "magician:red", + .default_trigger = "ds2760-battery.0-charging", + }, + .hw_num = 0, + .bit2 = PASIC3_BIT2_LED0, + .mask = PASIC3_MASK_LED0, + }, + { + .led = { + .name = "magician:green", + .default_trigger = "ds2760-battery.0-charging-or-full", + }, + .hw_num = 1, + .bit2 = PASIC3_BIT2_LED1, + .mask = PASIC3_MASK_LED1, + }, + { + .led = { + .name = "magician:blue", + .default_trigger = "bluetooth", + }, + .hw_num = 2, + .bit2 = PASIC3_BIT2_LED2, + .mask = PASIC3_MASK_LED2, + }, +}; + +static struct pasic3_leds_machinfo pasic3_leds_info = { + .num_leds = ARRAY_SIZE(pasic3_leds), + .power_gpio = EGPIO_MAGICIAN_LED_POWER, + .leds = pasic3_leds, +}; + +/* + * PASIC3 with DS1WM + */ + +static struct resource pasic3_resources[] = { + [0] = { + .start = PXA_CS2_PHYS, + .end = PXA_CS2_PHYS + 0x1b, + .flags = IORESOURCE_MEM, + }, + /* No IRQ handler in the PASIC3, DS1WM needs an external IRQ */ + [1] = { + .start = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ), + .end = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, + } +}; + +static struct pasic3_platform_data pasic3_platform_data = { + .led_pdata = &pasic3_leds_info, + .clock_rate = 4000000, +}; + +static struct platform_device pasic3 = { + .name = "pasic3", + .id = -1, + .num_resources = ARRAY_SIZE(pasic3_resources), + .resource = pasic3_resources, + .dev = { + .platform_data = &pasic3_platform_data, + }, +}; + +/* + * USB "Transceiver" + */ + +static struct resource gpio_vbus_resource = { + .flags = IORESOURCE_IRQ, + .start = IRQ_MAGICIAN_VBUS, + .end = IRQ_MAGICIAN_VBUS, +}; + +static struct gpio_vbus_mach_info gpio_vbus_info = { + .gpio_pullup = GPIO27_MAGICIAN_USBC_PUEN, + .gpio_vbus = EGPIO_MAGICIAN_CABLE_STATE_USB, }; +static struct platform_device gpio_vbus = { + .name = "gpio-vbus", + .id = -1, + .num_resources = 1, + .resource = &gpio_vbus_resource, + .dev = { + .platform_data = &gpio_vbus_info, + }, +}; /* * External power */ -static int magician_is_ac_online(void) +static int power_supply_init(struct device *dev) { - return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC); + return gpio_request(EGPIO_MAGICIAN_CABLE_STATE_AC, "CABLE_STATE_AC"); } -static int magician_is_usb_online(void) +static int magician_is_ac_online(void) { - return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_USB); + return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC); } -static void magician_set_charge(int flags) +static void power_supply_exit(struct device *dev) { - gpio_set_value(GPIO30_MAGICIAN_nCHARGE_EN, !flags); - gpio_set_value(EGPIO_MAGICIAN_CHARGE_EN, flags); + gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC); } +static char *magician_supplicants[] = { + "ds2760-battery.0", "backup-battery" +}; + static struct pda_power_pdata power_supply_info = { - .is_ac_online = magician_is_ac_online, - .is_usb_online = magician_is_usb_online, - .set_charge = magician_set_charge, + .init = power_supply_init, + .is_ac_online = magician_is_ac_online, + .exit = power_supply_exit, + .supplied_to = magician_supplicants, + .num_supplicants = ARRAY_SIZE(magician_supplicants), }; static struct resource power_supply_resources[] = { [0] = { .name = "ac", - .flags = IORESOURCE_IRQ, - .start = IRQ_MAGICIAN_AC, - .end = IRQ_MAGICIAN_AC, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | + IORESOURCE_IRQ_LOWEDGE, + .start = IRQ_MAGICIAN_VBUS, + .end = IRQ_MAGICIAN_VBUS, }, [1] = { .name = "usb", - .flags = IORESOURCE_IRQ, - .start = IRQ_MAGICIAN_AC, - .end = IRQ_MAGICIAN_AC, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | + IORESOURCE_IRQ_LOWEDGE, + .start = IRQ_MAGICIAN_VBUS, + .end = IRQ_MAGICIAN_VBUS, }, }; @@ -351,6 +581,43 @@ static struct platform_device power_supply = { .num_resources = ARRAY_SIZE(power_supply_resources), }; +/* + * Battery charger + */ + +static struct regulator_consumer_supply bq24022_consumers[] = { + { + .dev = &gpio_vbus.dev, + .supply = "vbus_draw", + }, + { + .dev = &power_supply.dev, + .supply = "ac_draw", + }, +}; + +static struct regulator_init_data bq24022_init_data = { + .constraints = { + .max_uA = 500000, + .valid_ops_mask = REGULATOR_CHANGE_CURRENT, + }, + .num_consumer_supplies = ARRAY_SIZE(bq24022_consumers), + .consumer_supplies = bq24022_consumers, +}; + +static struct bq24022_mach_info bq24022_info = { + .gpio_nce = GPIO30_MAGICIAN_BQ24022_nCHARGE_EN, + .gpio_iset2 = EGPIO_MAGICIAN_BQ24022_ISET2, + .init_data = &bq24022_init_data, +}; + +static struct platform_device bq24022 = { + .name = "bq24022", + .id = -1, + .dev = { + .platform_data = &bq24022_info, + }, +}; /* * MMC/SD @@ -361,19 +628,7 @@ static int magician_mci_init(struct device *dev, { return request_irq(IRQ_MAGICIAN_SD, detect_irq, IRQF_DISABLED | IRQF_SAMPLE_RANDOM, - "MMC card detect", data); -} - -static void magician_mci_setpower(struct device *dev, unsigned int vdd) -{ - struct pxamci_platform_data *pdata = dev->platform_data; - - gpio_set_value(EGPIO_MAGICIAN_SD_POWER, (1 << vdd) & pdata->ocr_mask); -} - -static int magician_mci_get_ro(struct device *dev) -{ - return (!gpio_get_value(EGPIO_MAGICIAN_nSD_READONLY)); + "mmc card detect", data); } static void magician_mci_exit(struct device *dev, void *data) @@ -382,11 +637,13 @@ static void magician_mci_exit(struct device *dev, void *data) } static struct pxamci_platform_data magician_mci_info = { - .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, - .init = magician_mci_init, - .get_ro = magician_mci_get_ro, - .setpower = magician_mci_setpower, - .exit = magician_mci_exit, + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = magician_mci_init, + .exit = magician_mci_exit, + .gpio_card_detect = -1, + .gpio_card_ro = EGPIO_MAGICIAN_nSD_READONLY, + .gpio_card_ro_invert = 1, + .gpio_power = EGPIO_MAGICIAN_SD_POWER, }; @@ -394,18 +651,10 @@ static struct pxamci_platform_data magician_mci_info = { * USB OHCI */ -static int magician_ohci_init(struct device *dev) -{ - UHCHR = (UHCHR | UHCHR_SSEP2 | UHCHR_PCPL | UHCHR_CGR) & - ~(UHCHR_SSEP1 | UHCHR_SSEP3 | UHCHR_SSE); - - return 0; -} - static struct pxaohci_platform_data magician_ohci_info = { - .port_mode = PMM_PERPORT_MODE, - .init = magician_ohci_init, - .power_budget = 0, + .port_mode = PMM_PERPORT_MODE, + .flags = ENABLE_PORT1 | ENABLE_PORT3 | POWER_CONTROL_LOW, + .power_budget = 0, }; @@ -418,11 +667,9 @@ static void magician_set_vpp(struct map_info *map, int vpp) gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, vpp); } -#define PXA_CS_SIZE 0x04000000 - static struct resource strataflash_resource = { .start = PXA_CS0_PHYS, - .end = PXA_CS0_PHYS + PXA_CS_SIZE - 1, + .end = PXA_CS0_PHYS + SZ_64M - 1, .flags = IORESOURCE_MEM, }; @@ -442,6 +689,14 @@ static struct platform_device strataflash = { }; /* + * I2C + */ + +static struct i2c_pxa_platform_data i2c_info = { + .fast_mode = 1, +}; + +/* * Platform devices */ @@ -449,34 +704,59 @@ static struct platform_device *devices[] __initdata = { &gpio_keys, &egpio, &backlight, + &pasic3, + &bq24022, + &gpio_vbus, &power_supply, &strataflash, + &leds_gpio, }; static void __init magician_init(void) { void __iomem *cpld; int lcd_select; + int err; + + gpio_request(GPIO13_MAGICIAN_CPLD_IRQ, "CPLD_IRQ"); + gpio_request(GPIO107_MAGICIAN_DS1WM_IRQ, "DS1WM_IRQ"); - platform_add_devices(devices, ARRAY_SIZE(devices)); - pxa_set_i2c_info(NULL); + pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config)); + + pxa_set_ffuart_info(NULL); + pxa_set_btuart_info(NULL); + pxa_set_stuart_info(NULL); + + platform_add_devices(ARRAY_AND_SIZE(devices)); + + err = gpio_request(GPIO83_MAGICIAN_nIR_EN, "nIR_EN"); + if (!err) { + gpio_direction_output(GPIO83_MAGICIAN_nIR_EN, 1); + pxa_set_ficp_info(&magician_ficp_info); + } + pxa27x_set_i2c_power_info(NULL); + pxa_set_i2c_info(&i2c_info); pxa_set_mci_info(&magician_mci_info); pxa_set_ohci_info(&magician_ohci_info); - pxa_set_ficp_info(&magician_ficp_info); /* Check LCD type we have */ cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000); if (cpld) { u8 board_id = __raw_readb(cpld+0x14); + iounmap(cpld); system_rev = board_id & 0x7; lcd_select = board_id & 0x8; - iounmap(cpld); pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly"); - if (lcd_select && (system_rev < 3)) - pxa_gpio_mode(GPIO75_MAGICIAN_SAMSUNG_POWER_MD); - pxa_gpio_mode(GPIO104_MAGICIAN_LCD_POWER_1_MD); - pxa_gpio_mode(GPIO105_MAGICIAN_LCD_POWER_2_MD); - pxa_gpio_mode(GPIO106_MAGICIAN_LCD_POWER_3_MD); + if (lcd_select && (system_rev < 3)) { + gpio_request(GPIO75_MAGICIAN_SAMSUNG_POWER, "SAMSUNG_POWER"); + gpio_direction_output(GPIO75_MAGICIAN_SAMSUNG_POWER, 0); + } + gpio_request(GPIO104_MAGICIAN_LCD_POWER_1, "LCD_POWER_1"); + gpio_request(GPIO105_MAGICIAN_LCD_POWER_2, "LCD_POWER_2"); + gpio_request(GPIO106_MAGICIAN_LCD_POWER_3, "LCD_POWER_3"); + gpio_direction_output(GPIO104_MAGICIAN_LCD_POWER_1, 0); + gpio_direction_output(GPIO105_MAGICIAN_LCD_POWER_2, 0); + gpio_direction_output(GPIO106_MAGICIAN_LCD_POWER_3, 0); set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info); } else pr_err("LCD detection: CPLD mapping failed\n");