Index: linux-2.6.23/arch/arm/mach-pxa/ezx-emu.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.23/arch/arm/mach-pxa/ezx-emu.c 2007-10-23 15:57:50.000000000 +0200 @@ -0,0 +1,219 @@ +/* + * 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); +static int emu_irq_usb4v; +static int emu_irq_usb1v; + + +#if defined CONFIG_EZX_EMU_USB +#define emu_switch_to_default() emu_switch_to_usb() +#elif defined CONFIG_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) +{ + printk(KERN_NOTICE "EMU: Switching to USB\n"); + 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(PCAP_BIT_BUSCTRL_RS232ENB, 1); + ezx_pcap_bit_set(PCAP_BIT_BUSCTRL_FSENB, 0); + ezx_pcap_bit_set(PCAP_BIT_BUSCTRL_VUSB_EN, 1); + clr_GPIO(GPIO_EMU_MUX1); + clr_GPIO(GPIO_EMU_MUX2); +} + +void emu_switch_to_uart(void) +{ + printk(KERN_NOTICE "EMU: Switching to UART\n"); + ezx_pcap_bit_set(PCAP_BIT_BUSCTRL_VUSB_EN,0); + ezx_pcap_bit_set(PCAP_BIT_BUSCTRL_RS232ENB, 0); + ezx_pcap_bit_set(PCAP_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); + pxa_set_cken(CKEN_FFUART, 1); + clr_GPIO(GPIO_EMU_MUX1); + clr_GPIO(GPIO_EMU_MUX2); + +} + +void emu_switch_to_audio(int stereo) +{ + printk(KERN_NOTICE "EMU: Switching to audio(%s)\n", (stereo ? "stereo" : "mono")); + 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) +{ + printk(KERN_NOTICE "EMU: Switching to disconnected\n"); + ezx_pcap_bit_set(PCAP_BIT_BUSCTRL_VUSB_EN, 0); + ezx_pcap_bit_set(PCAP_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(pbit(PCAP_REG_PSTAT, PCAP_IRQ_USB4V))) + emu_switch_to_default(); + break; + case EZX_IRQ_USB1V: + if(!ezx_pcap_read_bit(pbit(PCAP_REG_PSTAT, PCAP_IRQ_USB1V))) + 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); + + emu_irq_usb4v = platform_get_irq(dev, 0); + if(emu_irq_usb4v < 0) { + printk(KERN_ERR "Unable to get IRQ for USB4V!\n"); + return emu_irq_usb4v; + } + emu_irq_usb1v = platform_get_irq(dev, 1); + if(emu_irq_usb1v < 0) { + printk(KERN_ERR "Unable to get IRQ for USB1V!\n"); + return emu_irq_usb1v; + } + + request_irq(emu_irq_usb4v, &emu_irq, IRQF_DISABLED, "usb 4v", NULL); + request_irq(emu_irq_usb1v, &emu_irq, IRQF_DISABLED, "usb 1v", NULL); + + pxa_set_udc_info(&ezx_udc_info); + + if(ezx_pcap_read_bit(pbit(PCAP_REG_PSTAT, PCAP_IRQ_USB4V))) + emu_switch_to_default(); + else + emu_switch_to_nothing(); + + return 0; +} + +static int ezx_emu_remove(struct platform_device *dev) +{ + free_irq(emu_irq_usb4v, NULL); + free_irq(emu_irq_usb1v, NULL); + + 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(PCAP_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(PCAP_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, + .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.23/arch/arm/mach-pxa/Kconfig =================================================================== --- linux-2.6.23.orig/arch/arm/mach-pxa/Kconfig 2007-10-23 15:38:53.000000000 +0200 +++ linux-2.6.23/arch/arm/mach-pxa/Kconfig 2007-10-23 18:00:57.000000000 +0200 @@ -112,6 +112,28 @@ config EZX_PCAP bool "PCAP Support" +config EZX_EMU + bool "Motorola Enchanced Mini Usb" + depends on EZX_PCAP + +if EZX_EMU + +choice + prompt "Select default EMU mode" + +config EZX_EMU_USB + bool "USB" + +config EZX_EMU_UART + bool "UART" + +config EZX_EMU_NOTHING + bool "nothing" + +endchoice + +endif + endif endmenu Index: linux-2.6.23/arch/arm/mach-pxa/Makefile =================================================================== --- linux-2.6.23.orig/arch/arm/mach-pxa/Makefile 2007-10-23 15:38:53.000000000 +0200 +++ linux-2.6.23/arch/arm/mach-pxa/Makefile 2007-10-23 18:00:57.000000000 +0200 @@ -27,6 +27,7 @@ obj-$(CONFIG_PXA_EZX_E6) += ezx-e6.o obj-$(CONFIG_EZX_BP) += ezx-bp.o obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o +obj-$(CONFIG_EZX_EMU) += ezx-emu.o # Support for blinky lights led-y := leds.o