Index: linux-2.6.21/arch/arm/mach-pxa/ezx-emu.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.21/arch/arm/mach-pxa/ezx-emu.c 2007-05-02 23:30:15.000000000 -0300 @@ -0,0 +1,215 @@ +/* + * EMU Driver for Motorola EZX phones + * + * Copyright (c) 2007 Daniel Ribeiro + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static struct pxa2xx_udc_mach_info ezx_udc_info; +extern int ezx_pcap_bit_set(u_int32_t, u_int8_t); +extern int ezx_pcap_read_bit(u_int32_t); + +#if defined CONFIG_PXA_EZX_EMU_USB +#define emu_switch_to_default() emu_switch_to_usb() +#elif defined CONFIG_PXA_EZX_EMU_UART +#define emu_switch_to_default() emu_switch_to_uart() +#else +#define emu_switch_to_default() emu_switch_to_nothing() +#endif + +void emu_switch_to_usb(void) +{ + pxa_gpio_mode(GPIO34_USB_P2_2_MD); + pxa_gpio_mode(GPIO35_USB_P2_1_MD); + pxa_gpio_mode(GPIO36_USB_P2_4_MD); + pxa_gpio_mode(GPIO39_USB_P2_6_MD); + pxa_gpio_mode(GPIO40_USB_P2_5_MD); + pxa_gpio_mode(GPIO53_USB_P2_3_MD); + UP2OCR = 0x02000000; + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_RS232ENB, 1); + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_FSENB, 0); + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_VUSB_EN, 1); + clr_GPIO(GPIO_EMU_MUX1); + clr_GPIO(GPIO_EMU_MUX2); +} + +void emu_switch_to_uart(void) +{ + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_VUSB_EN,0); + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_RS232ENB, 0); + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_RS232_DIR, 1); + set_GPIO(GPIO39_FFTXD); + pxa_gpio_mode(GPIO34_TXENB | GPIO_OUT); + set_GPIO(GPIO34_TXENB); + pxa_gpio_mode(GPIO35_XRXD | GPIO_IN); + pxa_gpio_mode(GPIO36_VMOUT | GPIO_IN); + pxa_gpio_mode(GPIO40_VPIN | GPIO_IN); + pxa_gpio_mode(GPIO39_FFTXD_MD); + pxa_gpio_mode(GPIO53_FFRXD_MD); + CKEN |= CKEN6_FFUART; + clr_GPIO(GPIO_EMU_MUX1); + clr_GPIO(GPIO_EMU_MUX2); + +} + +void emu_switch_to_audio(int stereo) +{ + clr_GPIO(GPIO39_VPOUT); + if (stereo) { + pxa_gpio_mode(GPIO34_TXENB | GPIO_IN); + clr_GPIO(GPIO39_VPOUT); + } else { + pxa_gpio_mode(GPIO34_TXENB | GPIO_OUT); + set_GPIO(GPIO34_TXENB); + } + + pxa_gpio_mode(GPIO35_XRXD | GPIO_IN); + pxa_gpio_mode(GPIO36_VMOUT | GPIO_IN); + pxa_gpio_mode(GPIO39_VPOUT | GPIO_IN); + pxa_gpio_mode(GPIO40_VPIN | GPIO_IN); + pxa_gpio_mode(GPIO53_VMIN | GPIO_IN); + set_GPIO(GPIO_EMU_MUX1); + if (stereo) + set_GPIO(GPIO_EMU_MUX2); + else + clr_GPIO(GPIO_EMU_MUX2); +} + +void emu_switch_to_nothing(void) +{ + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_VUSB_EN, 0); + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_RS232ENB, 1); + pxa_gpio_mode(GPIO34_TXENB | GPIO_OUT); + set_GPIO(GPIO34_TXENB); + pxa_gpio_mode(GPIO35_XRXD | GPIO_IN); + pxa_gpio_mode(GPIO36_VMOUT | GPIO_IN); + pxa_gpio_mode(GPIO39_VPOUT | GPIO_IN); + pxa_gpio_mode(GPIO40_VPIN | GPIO_IN); + pxa_gpio_mode(GPIO53_VMIN | GPIO_IN); +} + + +static irqreturn_t emu_irq(int irq, void *data) +{ + switch (irq) { + case EZX_IRQ_USB4V: + if(ezx_pcap_read_bit(SSP_PCAP_ADJ_BIT_PSTAT_USBDET_4V)) + emu_switch_to_default(); + break; + case EZX_IRQ_USB1V: + if(!ezx_pcap_read_bit(SSP_PCAP_ADJ_BIT_PSTAT_USBDET_1V)) + emu_switch_to_nothing(); + break; + } + + return IRQ_HANDLED; +} + +static int __init ezx_emu_probe(struct platform_device *dev) +{ + pxa_gpio_mode(GPIO_SNP_INT_IN | GPIO_IN); + pxa_gpio_mode(GPIO_EMU_MUX1 | GPIO_OUT); + pxa_gpio_mode(GPIO_EMU_MUX2 | GPIO_OUT); + + request_irq(EZX_IRQ_USB4V, &emu_irq, SA_INTERRUPT, "usb 4v", NULL); + request_irq(EZX_IRQ_USB1V, &emu_irq, SA_INTERRUPT, "usb 1v", NULL); + + pxa_set_udc_info(&ezx_udc_info); + + if(ezx_pcap_read_bit(SSP_PCAP_ADJ_BIT_PSTAT_USBDET_4V)) + emu_switch_to_default(); + else + emu_switch_to_nothing(); + + return 0; +} + +static int ezx_emu_remove(struct platform_device *dev) +{ + free_irq(EZX_IRQ_USB4V, NULL); + free_irq(EZX_IRQ_USB1V, NULL); + + return 0; +} + +static int ezx_emu_suspend(struct platform_device *dev, pm_message_t state) +{ + emu_switch_to_nothing(); + return 0; +} + +static int ezx_emu_resume(struct platform_device *dev) +{ + emu_switch_to_default(); + return 0; +} + +/* USB Device Controller */ +static int udc_connected_status; +static void ezx_udc_command(int cmd) +{ + switch (cmd) { + case PXA2XX_UDC_CMD_DISCONNECT: + printk(KERN_NOTICE "USB cmd disconnect\n"); + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_USB_PU,0); + udc_connected_status = 0; + break; + case PXA2XX_UDC_CMD_CONNECT: + printk(KERN_NOTICE "USB cmd connect\n"); + ezx_pcap_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_USB_PU,1); + udc_connected_status = 1; + break; + } +} + +static int ezx_udc_is_connected(void) +{ + return udc_connected_status; +} + +static struct pxa2xx_udc_mach_info ezx_udc_info __initdata = { + .udc_is_connected = ezx_udc_is_connected, + .udc_command = ezx_udc_command, +}; + +static struct platform_driver ezxemu_driver = { + .probe = ezx_emu_probe, + .remove = ezx_emu_remove, + .suspend = ezx_emu_suspend, + .resume = ezx_emu_resume, + .driver = { + .name = "ezx-emu", + .owner = THIS_MODULE, + }, +}; + +int __init ezx_emu_init(void) +{ + return platform_driver_register(&ezxemu_driver); +} + +void ezx_emu_fini(void) +{ + return platform_driver_unregister(&ezxemu_driver); +} + +module_init(ezx_emu_init); +module_exit(ezx_emu_fini); + +MODULE_DESCRIPTION("Motorola Enchanced Mini Usb driver"); +MODULE_AUTHOR("Daniel Ribeiro "); +MODULE_LICENSE("GPL"); Index: linux-2.6.21/arch/arm/mach-pxa/Kconfig =================================================================== --- linux-2.6.21.orig/arch/arm/mach-pxa/Kconfig 2007-05-02 21:31:22.000000000 -0300 +++ linux-2.6.21/arch/arm/mach-pxa/Kconfig 2007-05-02 23:26:53.000000000 -0300 @@ -94,6 +94,27 @@ endchoice +config PXA_EZX_EMU + bool "Motorola Enchanced Mini Usb" + +if PXA_EZX_EMU + +choice + prompt "Select default EMU mode" + +config PXA_EZX_EMU_USB + bool "USB" + +config PXA_EZX_EMU_UART + bool "UART" + +config PXA_EZX_EMU_NOTHING + bool "nothing" + +endchoice + +endif + endif endmenu Index: linux-2.6.21/arch/arm/mach-pxa/Makefile =================================================================== --- linux-2.6.21.orig/arch/arm/mach-pxa/Makefile 2007-05-02 23:26:52.000000000 -0300 +++ linux-2.6.21/arch/arm/mach-pxa/Makefile 2007-05-03 17:41:40.000000000 -0300 @@ -19,6 +19,7 @@ obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o obj-$(CONFIG_MACH_TOSA) += tosa.o obj-$(CONFIG_PXA_EZX) += ezx.o ezx_lcd.o ezx_ssp.o ezx-pcap.o ezx-mci.o +obj-$(CONFIG_PXA_EZX_EMU) += ezx-emu.o # Support for blinky lights led-y := leds.o Index: linux-2.6.21/arch/arm/mach-pxa/ezx.c =================================================================== --- linux-2.6.21.orig/arch/arm/mach-pxa/ezx.c 2007-05-02 23:26:52.000000000 -0300 +++ linux-2.6.21/arch/arm/mach-pxa/ezx.c 2007-05-03 17:25:08.000000000 -0300 @@ -35,6 +35,7 @@ #include #include + #include "ezx.h" #include "generic.h" #include @@ -91,6 +92,30 @@ .resource = ezxpcap_resources, }; +/* EMU */ +static struct resource ezxemu_resources[] = { + [0] = { + .start = EZX_IRQ_USB4V, + .end = EZX_IRQ_USB4V, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .start = EZX_IRQ_USB1V, + .end = EZX_IRQ_USB1V, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device ezxemu_device = { + .name = "ezx-emu", + .id = -1, + .dev = { + .parent = &ezxpcap_device.dev, + }, + .num_resources = ARRAY_SIZE(ezxemu_resources), + .resource = ezxemu_resources, +}; + /* OHCI Controller */ static int ezx_ohci_init(struct device *dev) @@ -316,6 +341,7 @@ &ezxssp_device, &ezxpcap_device, &ezxbp_device, + &ezxemu_device, }; static void __init a780_init(void)