Index: linux-2.6.24/arch/arm/mach-pxa/ezx-pcap.c =================================================================== --- /dev/null +++ linux-2.6.24/arch/arm/mach-pxa/ezx-pcap.c @@ -0,0 +1,513 @@ +/* Driver for Motorola PCAP2 as present in EZX phones + * + * This is both a SPI device driver for PCAP itself, as well as + * an IRQ demultiplexer for handling PCAP generated events such as + * headphone jack sense by downstream drivers. + * + * Copyright (C) 2006 Harald Welte + * Copyright (C) 2007 Daniel Ribeiro + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#if 0 +#define DEBUGP(x, args...) printk(x, ## args) +#else +#define DEBUGP(x, args...) +#endif + +static DEFINE_SPINLOCK(ezx_ssp_lock); +static struct ssp_dev ezx_ssp_dev; +static struct ssp_state ezx_ssp_state; +static struct pcap_platform_data *pcap_data; +static int pcap_irq; + +static unsigned long ezx_ssp_pcap_putget(ulong data) +{ + unsigned long flag; + u32 ret = 0; + + spin_lock_irqsave(&ezx_ssp_lock, flag); + if (pcap_data->cs >= 0) { + if (pcap_data->flags & PCAP_CS_AH) + GPSR(pcap_data->cs) = GPIO_bit(pcap_data->cs); + else + GPCR(pcap_data->cs) = GPIO_bit(pcap_data->cs); + } + + ssp_write_word(&ezx_ssp_dev,data); + ssp_read_word(&ezx_ssp_dev, &ret); + + if (pcap_data->cs >= 0) { + if(pcap_data->flags & PCAP_CS_AH) + GPCR(pcap_data->cs) = GPIO_bit(pcap_data->cs); + else + GPSR(pcap_data->cs) = GPIO_bit(pcap_data->cs); + } + + spin_unlock_irqrestore(&ezx_ssp_lock, flag); + + return ret; +} + +int ezx_pcap_write(u_int8_t reg_num, u_int32_t value) +{ + value &= PCAP_REGISTER_VALUE_MASK; + value |= PCAP_REGISTER_WRITE_OP_BIT + | (reg_num<> PCAP_REGISTER_ADDRESS_SHIFT; + + ret = ezx_pcap_read(reg_num, &tmp); + if (ret < 0) + return ret; + + if (to == 0) + tmp &= ~bit; + else + tmp |= bit; + + return ezx_pcap_write(reg_num, tmp); +} +EXPORT_SYMBOL_GPL(ezx_pcap_bit_set); + +int ezx_pcap_read_bit(u_int32_t bit) +{ + int ret; + u_int32_t tmp; + u_int8_t reg_num = (bit & PCAP_REGISTER_ADDRESS_MASK) + >> PCAP_REGISTER_ADDRESS_SHIFT; + + ret = ezx_pcap_read(reg_num, &tmp); + if (ret < 0) + return ret; + + return tmp & (bit & PCAP_REGISTER_VALUE_MASK); +} +EXPORT_SYMBOL_GPL(ezx_pcap_read_bit); + +/* /proc/pcap support */ +#ifdef CONFIG_PROC_FS + +static struct proc_dir_entry *proc_pcap; + +char *pcap_registers[] = { + "ISR\t", "MSR\t", "PSTAT\t", "INT_SEL\t", "SWCTRL\t", "VREG1\t", + "VREG2\t", "VREG\t", "BATT_DAC", "ADC1\t", "ADC2\t", "AUD_CODEC", + "RX_AUD_AMPS", "ST_DAC\t", "RTC_TOD\t", "RTC_TODA", "RTC_DAY\t", + "RTC_DAYA", "MTRTMR\t", "PWRCTRL\t", "BUSCTRL\t", "PERIPH\t", + "AUXVREG_MASK", "VENDOR_REV", "LOWPWR_CTRL", "PERIPH_MASK", + "TX_AUD_AMPS", "GP\t", + NULL, NULL, NULL, NULL +}; + +static int pcap_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data_unused) +{ + int len = 0; + u_int8_t r; + u_int32_t v; + off_t begin = 0; + + for(r = 0; r < 32; r++) { + if (pcap_registers[r] == NULL) + continue; + ezx_pcap_read(r, &v); + len += sprintf(page+len, "%s\t%08X\n", pcap_registers[r], v); + if(len + begin > off + count) + goto done; + if(len + begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; +done: + if (off >= len+begin) + return 0; + *start = page + (off-begin); + return ((count < begin+len-off) ? count : begin+len-off); +} +#endif + +void ezx_pcap_vibrator_level(u_int32_t value) +{ + u_int32_t tmp; + + ezx_pcap_read(PCAP_REG_AUXVREG, &tmp); + + tmp &= ~PCAP_AUXVREG_V_VIB_MASK; + tmp |= ((value << PCAP_AUXVREG_V_VIB_SHIFT) & PCAP_AUXVREG_V_VIB_MASK); + + ezx_pcap_write(PCAP_REG_AUXVREG, tmp); +} +EXPORT_SYMBOL_GPL(ezx_pcap_vibrator_level); + +/* MMC/SD specific functions */ + +void ezx_pcap_mmcsd_voltage(u_int32_t bits) +{ + unsigned int tmp; + ezx_pcap_read(PCAP_REG_AUXVREG, &tmp); + if (pcap_data->flags & PCAP_MCI_SD) { + tmp &= ~PCAP_AUXVREG_VAUX2_MASK; + tmp |= ((bits << PCAP_AUXVREG_VAUX2_SHIFT) & + PCAP_AUXVREG_VAUX2_MASK); + } + else if (pcap_data->flags & PCAP_MCI_TF) { + tmp &= ~PCAP_AUXVREG_VAUX3_MASK; + tmp |= ((bits << PCAP_AUXVREG_VAUX3_SHIFT) & + PCAP_AUXVREG_VAUX3_MASK); + } + ezx_pcap_write(PCAP_REG_AUXVREG, tmp); +} +EXPORT_SYMBOL_GPL(ezx_pcap_mmcsd_voltage); + +int ezx_pcap_mmcsd_power(int on) +{ + if (on > 0) on = 1; + else on = 0; + + if (pcap_data->flags & PCAP_MCI_SD) + return ezx_pcap_bit_set(PCAP_BIT_AUXVREG_VAUX2_EN, on); + else if (pcap_data->flags & PCAP_MCI_TF) + return ezx_pcap_bit_set(PCAP_BIT_AUXVREG_VAUX3_EN, on); + else + return -ENODEV; +} +EXPORT_SYMBOL_GPL(ezx_pcap_mmcsd_power); + +/* IRQ Handling */ + +/* Array indexed by BIT POSITION of PCAP register, returns IRQ number */ +static unsigned int pcap2irq[] = { + [0] = EZX_IRQ_ADCDONE, + [1] = EZX_IRQ_TS, + [2] = EZX_IRQ_1HZ, /* 1HZ */ + [3] = EZX_IRQ_WH, /* WH */ + [4] = EZX_IRQ_WL, /* WL */ + [5] = EZX_IRQ_TODA, /* TODA */ + [6] = EZX_IRQ_USB4V, + [7] = EZX_IRQ_ONOFF, /* ONOFF */ + [8] = EZX_IRQ_ONOFF2, /* ONOFF2 */ + [9] = EZX_IRQ_USB1V, + [10] = EZX_IRQ_MOBPORT, /* MOBPORT */ + [11] = EZX_IRQ_MIC, + [12] = EZX_IRQ_HEADJACK, + [13] = EZX_IRQ_ST, /* ST */ + [14] = EZX_IRQ_PC, /* PC */ + [15] = EZX_IRQ_WARM, /* WARM */ + [16] = EZX_IRQ_EOL, /* EOL */ + [17] = EZX_IRQ_CLK, /* CLK */ + [18] = EZX_IRQ_SYSRST, /* SYSRST */ + [19] = 0, + [20] = EZX_IRQ_ADCDONE2, + [21] = EZX_IRQ_SOFTRESET, /* SOFTRESET */ + [22] = EZX_IRQ_MNEXB, /* MNEXB */ +}; + +/* Array indexed by IRQ NUMBER, returns PCAP absolute value */ +static unsigned int irq2pcap[] = { + [EZX_IRQ_MNEXB] = PCAP_IRQ_MNEXB, + [EZX_IRQ_SOFTRESET] = PCAP_IRQ_SOFTRESET, + [EZX_IRQ_SYSRST] = PCAP_IRQ_SYSRST, + [EZX_IRQ_CLK] = PCAP_IRQ_CLK, + [EZX_IRQ_EOL] = PCAP_IRQ_EOL, + [EZX_IRQ_WARM] = PCAP_IRQ_WARM, + [EZX_IRQ_PC] = PCAP_IRQ_PC, + [EZX_IRQ_ST] = PCAP_IRQ_ST, + [EZX_IRQ_MOBPORT] = PCAP_IRQ_MOBPORT, + [EZX_IRQ_ONOFF2] = PCAP_IRQ_ONOFF2, + [EZX_IRQ_ONOFF] = PCAP_IRQ_ONOFF, + [EZX_IRQ_TODA] = PCAP_IRQ_TODA, + [EZX_IRQ_WL] = PCAP_IRQ_WL, + [EZX_IRQ_WH] = PCAP_IRQ_WH, + [EZX_IRQ_1HZ] = PCAP_IRQ_1HZ, + [EZX_IRQ_USB4V] = PCAP_IRQ_USB4V, + [EZX_IRQ_USB1V] = PCAP_IRQ_USB1V, + [EZX_IRQ_HEADJACK] = PCAP_IRQ_A1, + [EZX_IRQ_MIC] = PCAP_IRQ_MB2, + [EZX_IRQ_TS] = PCAP_IRQ_TS, + [EZX_IRQ_ADCDONE] = PCAP_IRQ_ADCDONE, + [EZX_IRQ_ADCDONE2] = PCAP_IRQ_ADCDONE2, +}; + +static void pcap_ack_irq(unsigned int irq) +{ + DEBUGP("pcap_ack_irq: %u\n", irq); + ezx_pcap_write(PCAP_REG_ISR, irq2pcap[irq]); +} + +static void pcap_mask_irq(unsigned int irq) +{ + u_int32_t reg; + unsigned long flag; + + spin_lock_irqsave(&ezx_ssp_lock, flag); + DEBUGP("pcap_mask_irq: %u\n", irq); + ezx_pcap_read(PCAP_REG_MSR, ®); + reg |= irq2pcap[irq]; + ezx_pcap_write(PCAP_REG_MSR, reg); + spin_unlock_irqrestore(&ezx_ssp_lock, flag); +} + +static void pcap_unmask_irq(unsigned int irq) +{ + u_int32_t tmp; + unsigned long flag; + + spin_lock_irqsave(&ezx_ssp_lock, flag); + DEBUGP("pcap_unmask_irq: %u\n", irq); + ezx_pcap_read(PCAP_REG_MSR, &tmp); + tmp &= ~irq2pcap[irq]; + ezx_pcap_write(PCAP_REG_MSR, tmp); + spin_unlock_irqrestore(&ezx_ssp_lock, flag); +} + +static struct irq_chip pcap_chip = { + .ack = pcap_ack_irq, + .mask = pcap_mask_irq, + .unmask = pcap_unmask_irq, +}; + +/* handler for interrupt received from PCAP via GPIO */ +static void pcap_irq_demux_handler(unsigned int irq, struct irq_desc *desc) +{ + const unsigned int cpu = smp_processor_id(); + int i; + u_int32_t isr, msr; + + spin_lock(&desc->lock); + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + if (unlikely(desc->status & (IRQ_INPROGRESS | IRQ_DISABLED))) { + desc->status |= (IRQ_PENDING | IRQ_MASKED); + desc->chip->mask(irq); + desc->chip->ack(irq); + goto out_unlock; + } + kstat_cpu(cpu).irqs[irq]++; + desc->chip->ack(irq); + desc->status |= IRQ_INPROGRESS; + do { + if (unlikely((desc->status & + (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) == + (IRQ_PENDING | IRQ_MASKED))) { + desc->chip->unmask(irq); + desc->status &= ~IRQ_MASKED; + } + desc->status &= ~IRQ_PENDING; + + ezx_pcap_read(PCAP_REG_ISR, &isr); + ezx_pcap_read(PCAP_REG_MSR, &msr); + for (i = ARRAY_SIZE(pcap2irq)-1; i >= 0; i--) { + unsigned int pirq = pcap2irq[i]; + struct irq_desc *subdesc; + if (pirq == 0 || !(isr & irq2pcap[pirq])) + continue; + subdesc = irq_desc + pirq; + if (msr & irq2pcap[pirq]) + continue; + DEBUGP("found irq %u\n", pirq); + spin_unlock(&desc->lock); + desc_handle_irq(pirq, subdesc); + spin_lock(&desc->lock); + } + + } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); + + desc->status &= ~IRQ_INPROGRESS; +out_unlock: + spin_unlock(&desc->lock); +} + +static int ezx_pcap_remove(struct platform_device *pdev) +{ + int irq; + DEBUGP("exz_pcap_remove entered\n"); + + set_irq_chained_handler(pcap_irq, NULL); + + for (irq = EZX_IRQ(0); irq <= EZX_IRQ(21); irq++) { + set_irq_chip(irq, NULL); + set_irq_handler(irq, NULL); + set_irq_flags(irq, 0); + } + + ssp_exit(&ezx_ssp_dev); + + return 0; +} + +static int __init ezx_pcap_probe(struct platform_device *pdev) +{ + unsigned int ret, irq; + DEBUGP("ezx_pcap_probe entered\n"); + + pcap_data = pdev->dev.platform_data; + + /* configure ssp port */ + pxa_gpio_mode(29|GPIO_ALT_FN_3_OUT); + pxa_gpio_mode(GPIO24_SFRM_MD); + pxa_gpio_mode(GPIO25_STXD_MD); + pxa_gpio_mode(GPIO26_SRXD_MD); + + if (pcap_data->cs >= 0) { + if (pcap_data->flags & PCAP_CS_AH) + pxa_gpio_mode(pcap_data->cs | GPIO_OUT); + else + pxa_gpio_mode(pcap_data->cs | GPIO_OUT + | GPIO_DFLT_HIGH); + } + pcap_irq = platform_get_irq(pdev, 0); + if(pcap_irq < 0) { + printk(KERN_ERR "Unable to get IRQ for pcap!\n"); + return pcap_irq; + } + + ret = ssp_init(&ezx_ssp_dev, pcap_data->port, 0); + if (ret) { + printk(KERN_ERR "Unable to register SSP handler!\n"); + return ret; + } + + ssp_disable(&ezx_ssp_dev); + ssp_config(&ezx_ssp_dev, + (SSCR0_Motorola | SSCR0_DataSize(16) | SSCR0_EDSS), + (SSCR1_TxTresh(1) | SSCR1_RxTresh(1)), + 0, SSCR0_SerClkDiv(pcap_data->clk)); + ssp_enable(&ezx_ssp_dev); + + /* mask/ack all PCAP interrupts */ + ezx_pcap_write(PCAP_REG_MSR, PCAP_MASK_ALL_INTERRUPT); + ezx_pcap_write(PCAP_REG_ISR, PCAP_CLEAR_INTERRUPT_REGISTER); + + if (pcap_data->init) + pcap_data->init(); + + /* set up interrupt demultiplexing code for PCAP2 irqs */ + set_irq_type(pcap_irq, IRQT_RISING); + for (irq = EZX_IRQ(0); irq <= EZX_IRQ(21); irq++) { + set_irq_chip(irq, &pcap_chip); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + set_irq_chained_handler(pcap_irq, pcap_irq_demux_handler); + set_irq_wake(pcap_irq, 1); + + printk("ezx-pcap: ssp driver registered\n"); + return ret; +} + +static int ezx_pcap_suspend(struct platform_device *dev, pm_message_t state) +{ + DEBUGP("pcap suspend!\n"); + ssp_flush(&ezx_ssp_dev); + ssp_save_state(&ezx_ssp_dev, &ezx_ssp_state); + if (pcap_data->cs >= 0) + pxa_gpio_mode(pcap_data->cs | GPIO_IN); + return 0; +} + +static int ezx_pcap_resume(struct platform_device *dev) +{ + DEBUGP("pcap resume!\n"); + + if (pcap_data->cs >= 0) { + if (pcap_data->flags & PCAP_CS_AH) { + pxa_gpio_mode(pcap_data->cs | GPIO_OUT); + GPCR(pcap_data->cs) = GPIO_bit(pcap_data->cs); + } + else { + pxa_gpio_mode(pcap_data->cs | GPIO_OUT | GPIO_DFLT_HIGH); + GPSR(pcap_data->cs) = GPIO_bit(pcap_data->cs); + } + } + ssp_restore_state(&ezx_ssp_dev,&ezx_ssp_state); + ssp_enable(&ezx_ssp_dev); + + ezx_pcap_write(PCAP_REG_ISR, PCAP_CLEAR_INTERRUPT_REGISTER); + + return 0; +} + +static struct platform_driver ezxpcap_driver = { + .probe = ezx_pcap_probe, + .remove = ezx_pcap_remove, + .suspend = ezx_pcap_suspend, + .resume = ezx_pcap_resume, + .driver = { + .name = "ezx-pcap", + .owner = THIS_MODULE, + }, +}; + +static int __init ezx_pcap_init(void) +{ + DEBUGP("ezx_pcap_init entered\n"); + +#ifdef CONFIG_PROC_FS + if((proc_pcap = create_proc_entry("pcap", 0, NULL))) + proc_pcap->read_proc = pcap_read_proc; +#endif + + return platform_driver_register(&ezxpcap_driver); +} + +static void __exit ezx_pcap_exit(void) +{ +#ifdef CONFIG_PROC_FS + if (proc_pcap) + remove_proc_entry("pcap", NULL); +#endif + + return platform_driver_unregister(&ezxpcap_driver); +} + +module_init(ezx_pcap_init); +module_exit(ezx_pcap_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte"); +MODULE_DESCRIPTION("SPI Driver for Motorola PCAP2"); + Index: linux-2.6.24/include/asm-arm/arch-pxa/ezx-pcap.h =================================================================== --- /dev/null +++ linux-2.6.24/include/asm-arm/arch-pxa/ezx-pcap.h @@ -0,0 +1,248 @@ +/* + * Copyright 2007 Daniel Ribeiro + */ + +#ifndef EZX_PCAP_H +#define EZX_PCAP_H + +struct pcap_platform_data { + int port; /* SSP port */ + int cs; /* CS gpio */ + int clk; + int flags; /* driver flags */ + int (*init)(void); /* board specific driver init */ +}; + +/* driver configuration */ +#define PCAP_CS_AH (1 << 0) /* CS pin is active high */ +#define PCAP_MCI_SD (1 << 1) /* SD card slot */ +#define PCAP_MCI_TF (1 << 2) /* TF card slot */ + +#define PCAP_REGISTER_WRITE_OP_BIT 0x80000000 +#define PCAP_REGISTER_READ_OP_BIT 0x00000000 + +#define PCAP_REGISTER_VALUE_MASK 0x01ffffff +#define PCAP_REGISTER_ADDRESS_MASK 0x7c000000 +#define PCAP_REGISTER_ADDRESS_SHIFT 26 +#define PCAP_REGISTER_NUMBER 32 +#define PCAP_CLEAR_INTERRUPT_REGISTER 0x01ffffff +#define PCAP_MASK_ALL_INTERRUPT 0x01ffffff + + +#define pbit(reg, bit) ((reg << PCAP_REGISTER_ADDRESS_SHIFT) | bit) + +/* registers acessible by both pcap ports */ +#define PCAP_REG_ISR 0x0 /* Interrupt Status */ +#define PCAP_REG_MSR 0x1 /* Interrupt Mask */ +#define PCAP_REG_PSTAT 0x2 /* Processor Status */ +#define PCAP_REG_VREG2 0x6 /* Regulator Bank 2 Control */ +#define PCAP_REG_AUXVREG 0x7 /* Auxiliary Regulator Control */ +#define PCAP_REG_BATT 0x8 /* Battery Control */ +#define PCAP_REG_ADC1 0x9 /* AD Control */ +#define PCAP_REG_ADC2 0xa /* AD Result */ +#define PCAP_REG_CODEC 0xb /* Audio Codec Control */ +#define PCAP_REG_RX_AMPS 0xc /* RX Audio Amplifiers Control */ +#define PCAP_REG_ST_DAC 0xd /* Stereo DAC Control */ +#define PCAP_REG_BUSCTRL 0x14 /* Connectivity Control */ +#define PCAP_REG_PERIPH 0x15 /* Peripheral Control */ +#define PCAP_REG_LOWPWR 0x18 /* Regulator Low Power Control */ +#define PCAP_REG_TX_AMPS 0x1a /* TX Audio Amplifiers Control */ +#define PCAP_REG_GP 0x1b /* General Purpose */ + +/* registers acessible by pcap port 1 only (a1200, e2 & e6) */ +#define PCAP_REG_INT_SEL 0x3 /* Interrupt Select */ +#define PCAP_REG_SWCTRL 0x4 /* Switching Regulator Control */ +#define PCAP_REG_VREG1 0x5 /* Regulator Bank 1 Control */ +#define PCAP_REG_RTC_TOD 0xe /* RTC Time of Day */ +#define PCAP_REG_RTC_TODA 0xf /* RTC Time of Day Alarm */ +#define PCAP_REG_RTC_DAY 0x10 /* RTC Day */ +#define PCAP_REG_RTC_DAYA 0x11 /* RTC Day Alarm */ +#define PCAP_REG_MTRTMR 0x12 /* AD Monitor Timer */ +#define PCAP_REG_PWR 0x13 /* Power Control */ +#define PCAP_REG_AUXVREG_MASK 0x16 /* Auxiliary Regulator Mask */ +#define PCAP_REG_VENDOR_REV 0x17 +#define PCAP_REG_PERIPH_MASK 0x19 /* Peripheral Mask */ + +/* interrupts - registers 0, 1, 2, 3 */ +#define PCAP_IRQ_ADCDONE (1 << 0) /* AD Conversion Done Port 1 */ +#define PCAP_IRQ_TS (1 << 1) /* Touch Screen */ +#define PCAP_IRQ_1HZ (1 << 2) /* 1HZ Timer */ +#define PCAP_IRQ_WH (1 << 3) +#define PCAP_IRQ_WL (1 << 4) +#define PCAP_IRQ_TODA (1 << 5) +#define PCAP_IRQ_USB4V (1 << 6) +#define PCAP_IRQ_ONOFF (1 << 7) +#define PCAP_IRQ_ONOFF2 (1 << 8) +#define PCAP_IRQ_USB1V (1 << 9) +#define PCAP_IRQ_MOBPORT (1 << 10) +#define PCAP_IRQ_MB2 (1 << 11) /* Mic */ +#define PCAP_IRQ_A1 (1 << 12) /* Audio jack */ +#define PCAP_IRQ_ST (1 << 13) +#define PCAP_IRQ_PC (1 << 14) +#define PCAP_IRQ_WARM (1 << 15) +#define PCAP_IRQ_EOL (1 << 16) +#define PCAP_IRQ_CLK (1 << 17) +#define PCAP_IRQ_SYSRST (1 << 18) +#define PCAP_IRQ_ADCDONE2 (1 << 20) /* AD Conversion Done Port 2 */ +#define PCAP_IRQ_SOFTRESET (1 << 21) +#define PCAP_IRQ_MNEXB (1 << 22) + +#define PCAP_BIT_VREG2_V1_STBY pbit(PCAP_REG_VREG2, (1 << 0)) +#define PCAP_BIT_VREG2_V2_STBY pbit(PCAP_REG_VREG2, (1 << 1)) +#define PCAP_BIT_VREG2_V3_STBY pbit(PCAP_REG_VREG2, (1 << 2)) +#define PCAP_BIT_VREG2_V4_STBY pbit(PCAP_REG_VREG2, (1 << 3)) +#define PCAP_BIT_VREG2_V5_STBY pbit(PCAP_REG_VREG2, (1 << 4)) +#define PCAP_BIT_VREG2_V6_STBY pbit(PCAP_REG_VREG2, (1 << 5)) +#define PCAP_BIT_VREG2_V7_STBY pbit(PCAP_REG_VREG2, (1 << 6)) +#define PCAP_BIT_VREG2_V8_STBY pbit(PCAP_REG_VREG2, (1 << 7)) +#define PCAP_BIT_VREG2_V9_STBY pbit(PCAP_REG_VREG2, (1 << 8)) +#define PCAP_BIT_VREG2_V10_STBY pbit(PCAP_REG_VREG2, (1 << 9)) +#define PCAP_BIT_VREG2_V1_LOWPWR pbit(PCAP_REG_VREG2, (1 << 10)) +#define PCAP_BIT_VREG2_V2_LOWPWR pbit(PCAP_REG_VREG2, (1 << 11)) +#define PCAP_BIT_VREG2_V3_LOWPWR pbit(PCAP_REG_VREG2, (1 << 12)) +#define PCAP_BIT_VREG2_V4_LOWPWR pbit(PCAP_REG_VREG2, (1 << 13)) +#define PCAP_BIT_VREG2_V5_LOWPWR pbit(PCAP_REG_VREG2, (1 << 14)) +#define PCAP_BIT_VREG2_V6_LOWPWR pbit(PCAP_REG_VREG2, (1 << 15)) +#define PCAP_BIT_VREG2_V7_LOWPWR pbit(PCAP_REG_VREG2, (1 << 16)) +#define PCAP_BIT_VREG2_V8_LOWPWR pbit(PCAP_REG_VREG2, (1 << 17)) +#define PCAP_BIT_VREG2_V9_LOWPWR pbit(PCAP_REG_VREG2, (1 << 18)) +#define PCAP_BIT_VREG2_V10_LOWPWR pbit(PCAP_REG_VREG2, (1 << 19)) + +#define PCAP_BIT_AUXVREG_VAUX1_EN pbit(PCAP_REG_AUXVREG, (1 << 1)) +#define PCAP_AUXVREG_VAUX1_MASK 0x0000000c +#define PCAP_AUXVREG_VAUX1_SHIFT 2 +#define PCAP_BIT_AUXVREG_VAUX2_EN pbit(PCAP_REG_AUXVREG, (1 << 4)) +#define PCAP_AUXVREG_VAUX2_MASK 0x00000060 +#define PCAP_AUXVREG_VAUX2_SHIFT 5 +#define PCAP_BIT_AUXVREG_VAUX3_EN pbit(PCAP_REG_AUXVREG, (1 << 7)) +#define PCAP_AUXVREG_VAUX3_MASK 0x00000f00 +#define PCAP_AUXVREG_VAUX3_SHIFT 8 +#define PCAP_BIT_AUXVREG_VAUX4_EN pbit(PCAP_REG_AUXVREG, (1 << 12)) +#define PCAP_AUXVREG_VAUX4_MASK 0x00006000 +#define PCAP_AUXVREG_VAUX4_SHIFT 13 +#define PCAP_BIT_AUXVREG_VSIM2_EN pbit(PCAP_REG_AUXVREG, (1 << 16)) +#define PCAP_BIT_AUXVREG_VSIM_EN pbit(PCAP_REG_AUXVREG, (1 << 17)) +#define PCAP_BIT_AUXVREG_VSIM_0 pbit(PCAP_REG_AUXVREG, (1 << 18)) +#define PCAP_BIT_AUXVREG_V_VIB_EN pbit(PCAP_REG_AUXVREG, (1 << 19)) +#define PCAP_AUXVREG_V_VIB_MASK 0x00300000 +#define PCAP_AUXVREG_V_VIB_SHIFT 20 +#define PCAP_BIT_AUXVREG_VAUX1_STBY pbit(PCAP_REG_AUXVREG, (1 << 22)) +#define PCAP_BIT_AUXVREG_VAUX1_LOWPWR pbit(PCAP_REG_AUXVREG, (1 << 23)) +#define PCAP_BIT_AUXVREG_SW3_STBY pbit(PCAP_REG_AUXVREG, (1 << 24)) + +#define PCAP_BATT_DAC_MASK 0x000000ff +#define PCAP_BATT_DAC_SHIFT 0 +#define PCAP_BIT_BATT_B_FDBK pbit(PCAP_REG_BATT, (1 << 8)) +#define PCAP_BIT_BATT_EXT_ISENSE pbit(PCAP_REG_BATT, (1 << 9)) +#define PCAP_BATT_V_COIN_MASK 0x00003c00 +#define PCAP_BATT_V_COIN_SHIFT 10 +#define PCAP_BIT_BATT_I_COIN pbit(PCAP_REG_BATT, (1 << 14)) +#define PCAP_BIT_BATT_COIN_CH_EN pbit(PCAP_REG_BATT, (1 << 15)) +#define PCAP_BATT_EOL_SEL_MASK 0x000e0000 +#define PCAP_BATT_EOL_SEL_SHIFT 17 +#define PCAP_BIT_BATT_EOL_CMP_EN pbit(PCAP_REG_BATT, (1 << 20)) +#define PCAP_BIT_BATT_BATT_DET_EN pbit(PCAP_REG_BATT, (1 << 21)) +#define PCAP_BIT_BATT_THERMBIAS_CTRL pbit(PCAP_REG_BATT, (1 << 22)) + +#define PCAP_BIT_ADC1_ADEN pbit(PCAP_REG_ADC1, (1 << 0)) +#define PCAP_BIT_ADC1_RAND pbit(PCAP_REG_ADC1, (1 << 1)) +#define PCAP_BIT_ADC1_AD_SEL1 pbit(PCAP_REG_ADC1, (1 << 2)) +#define PCAP_BIT_ADC1_AD_SEL2 pbit(PCAP_REG_ADC1, (1 << 3)) +#define PCAP_ADC1_ADA1_MASK 0x00000070 +#define PCAP_ADC1_ADA1_SHIFT 4 +#define PCAP_ADC1_ADA2_MASK 0x00000380 +#define PCAP_ADC1_ADA2_SHIFT 7 +#define PCAP_ADC1_ATO_MASK 0x00003c00 +#define PCAP_ADC1_ATO_SHIFT 10 +#define PCAP_BIT_ADC1_ATOX pbit(PCAP_REG_ADC1, (1 << 14)) +#define PCAP_BIT_ADC1_MTR1 pbit(PCAP_REG_ADC1, (1 << 15)) +#define PCAP_BIT_ADC1_MTR2 pbit(PCAP_REG_ADC1, (1 << 16)) +#define PCAP_ADC1_TS_M_MASK 0x000e0000 +#define PCAP_ADC1_TS_M_SHIFT 17 +#define PCAP_BIT_ADC1_TS_REF_LOWPWR pbit(PCAP_REG_ADC1, (1 << 20)) +#define PCAP_BIT_ADC1_TS_REFENB pbit(PCAP_REG_ADC1, (1 << 21)) +#define PCAP_BIT_ADC1_BATT_I_POLARITY pbit(PCAP_REG_ADC1, (1 << 22)) +#define PCAP_BIT_ADC1_BATT_I_ADC pbit(PCAP_REG_ADC1, (1 << 23)) + +#define PCAP_ADC2_ADD1_MASK 0x000003ff +#define PCAP_ADC2_ADD1_SHIFT 0 +#define PCAP_ADC2_ADD2_MASK 0x000ffc00 +#define PCAP_ADC2_ADD2_SHIFT 10 +#define PCAP_BIT_ADC2_ADINC1 pbit(PCAP_REG_ADC2, (1 << 20)) +#define PCAP_BIT_ADC2_ADINC2 pbit(PCAP_REG_ADC2, (1 << 21)) +#define PCAP_BIT_ADC2_ASC pbit(PCAP_REG_ADC2, (1 << 22)) + +#define PCAP_BIT_BUSCTRL_FSENB 0x50000001 +#define PCAP_BIT_BUSCTRL_USB_SUSPEND 0x50000002 +#define PCAP_BIT_BUSCTRL_USB_PU 0x50000004 +#define PCAP_BIT_BUSCTRL_USB_PD 0x50000008 +#define PCAP_BIT_BUSCTRL_VUSB_EN 0x50000010 +#define PCAP_BIT_BUSCTRL_USB_PS 0x50000020 +#define PCAP_BIT_BUSCTRL_VUSB_MSTR_EN 0x50000040 +#define PCAP_BIT_BUSCTRL_VBUS_PD_ENB 0x50000080 +#define PCAP_BIT_BUSCTRL_CURRLIM 0x50000100 +#define PCAP_BIT_BUSCTRL_RS232ENB 0x50000200 +#define PCAP_BIT_BUSCTRL_RS232_DIR 0x50000400 +#define PCAP_BIT_BUSCTRL_SE0_CONN 0x50000800 +#define PCAP_BIT_BUSCTRL_USB_PDM 0x50001000 +#define PCAP_BIT_BUSCTRL_BUS_PRI_ADJ 0x51000000 + +#define PCAP_BIT_PERIPH_BL_CTRL0 0x54000001 +#define PCAP_BIT_PERIPH_BL_CTRL1 0x54000002 +#define PCAP_BIT_PERIPH_BL_CTRL2 0x54000004 +#define PCAP_BIT_PERIPH_BL_CTRL3 0x54000008 +#define PCAP_BIT_PERIPH_BL_CTRL4 0x54000010 +#define PCAP_BIT_PERIPH_LEDR_EN 0x54000020 +#define PCAP_BIT_PERIPH_LEDG_EN 0x54000040 +#define PCAP_BIT_PERIPH_LEDR_CTRL0 0x54000080 +#define PCAP_BIT_PERIPH_LEDR_CTRL1 0x54000100 +#define PCAP_BIT_PERIPH_LEDR_CTRL2 0x54000200 +#define PCAP_BIT_PERIPH_LEDR_CTRL3 0x54000400 +#define PCAP_BIT_PERIPH_LEDG_CTRL0 0x54000800 +#define PCAP_BIT_PERIPH_LEDG_CTRL1 0x54001000 +#define PCAP_BIT_PERIPH_LEDG_CTRL2 0x54002000 +#define PCAP_BIT_PERIPH_LEDG_CTRL3 0x54004000 +#define PCAP_BIT_PERIPH_LEDR_I0 0x54008000 +#define PCAP_BIT_PERIPH_LEDR_I1 0x54010000 +#define PCAP_BIT_PERIPH_LEDG_I0 0x54020000 +#define PCAP_BIT_PERIPH_LEDG_I1 0x54040000 +#define PCAP_BIT_PERIPH_SKIP 0x54080000 +#define PCAP_BIT_PERIPH_BL2_CTRL0 0x54100000 +#define PCAP_BIT_PERIPH_BL2_CTRL1 0x54200000 +#define PCAP_BIT_PERIPH_BL2_CTRL2 0x54400000 +#define PCAP_BIT_PERIPH_BL2_CTRL3 0x54800000 +#define PCAP_BIT_PERIPH_BL2_CTRL4 0x55000000 + +#define PCAP_BIT_LOWPWR_VAUX2_STBY 0x60000001 +#define PCAP_BIT_LOWPWR_VAUX2_LOWPWR 0x60000002 +#define PCAP_BIT_LOWPWR_VAUX3_STBY 0x60000004 +#define PCAP_BIT_LOWPWR_VAUX3_LOWPWR 0x60000008 +#define PCAP_BIT_LOWPWR_VAUX4_STBY 0x60000010 +#define PCAP_BIT_LOWPWR_VAUX4_LOWPWR 0x60000020 +#define PCAP_BIT_LOWPWR_VSIM_LOWPWR 0x60000040 +#define PCAP_BIT_LOWPWR_VSIM2_LOWPWR 0x60000080 +#define PCAP_BIT_LOWPWR_SW1_MODE00 0x60000100 +#define PCAP_BIT_LOWPWR_SW1_MODE01 0x60000200 +#define PCAP_BIT_LOWPWR_SW1_MODE10 0x60000400 +#define PCAP_BIT_LOWPWR_SW1_MODE11 0x60000800 +#define PCAP_BIT_LOWPWR_SW10_DVS 0x60001000 +#define PCAP_BIT_LOWPWR_SW11_DVS 0x60002000 +#define PCAP_BIT_LOWPWR_SW12_DVS 0x60004000 +#define PCAP_BIT_LOWPWR_SW13_DVS 0x60008000 +#define PCAP_BIT_LOWPWR_SW2_MODE00 0x60010000 +#define PCAP_BIT_LOWPWR_SW2_MODE01 0x60020000 +#define PCAP_BIT_LOWPWR_SW2_MODE10 0x60040000 +#define PCAP_BIT_LOWPWR_SW2_MODE11 0x60080000 +#define PCAP_BIT_LOWPWR_SW20_DVS 0x60100000 +#define PCAP_BIT_LOWPWR_SW21_DVS 0x60200000 +#define PCAP_BIT_LOWPWR_SW22_DVS 0x60400000 +#define PCAP_BIT_LOWPWR_SW23_DVS 0x60800000 +#define PCAP_BIT_LOWPWR_VC_STBY 0x61000000 + +extern int ezx_pcap_write(u_int8_t, u_int32_t); +extern int ezx_pcap_read(u_int8_t, u_int32_t *); +extern int ezx_pcap_bit_set(u_int32_t, u_int8_t); +extern int ezx_pcap_bit_get(u_int32_t); +extern int ezx_pcap_read_bit(u_int32_t); +extern void ezx_pcap_vibrator_level(u_int32_t); +#endif Index: linux-2.6.24/include/asm-arm/arch-pxa/irqs.h =================================================================== --- linux-2.6.24.orig/include/asm-arm/arch-pxa/irqs.h +++ linux-2.6.24/include/asm-arm/arch-pxa/irqs.h @@ -89,7 +89,7 @@ * within sensible limits. */ #define IRQ_BOARD_START (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM) -#define IRQ_BOARD_END (IRQ_BOARD_START + 16) +#define IRQ_BOARD_END (IRQ_BOARD_START + 22) #define IRQ_SA1111_START (IRQ_BOARD_END) #define IRQ_GPAIN0 (IRQ_BOARD_END + 0) @@ -180,7 +180,8 @@ #define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1) #elif defined(CONFIG_ARCH_LUBBOCK) || \ defined(CONFIG_MACH_LOGICPD_PXA270) || \ - defined(CONFIG_MACH_MAINSTONE) + defined(CONFIG_MACH_MAINSTONE) || \ + defined(CONFIG_PXA_EZX) #define NR_IRQS (IRQ_BOARD_END) #else #define NR_IRQS (IRQ_BOARD_START) @@ -227,6 +228,31 @@ #define IRQ_LOCOMO_LT_BASE (IRQ_BOARD_START + 2) #define IRQ_LOCOMO_SPI_BASE (IRQ_BOARD_START + 3) +/* EZX Interrupts (CONFIG_EZX) */ +#define EZX_IRQ(x) (IRQ_BOARD_START + (x)) +#define EZX_IRQ_USB4V EZX_IRQ(0) /* EMU */ +#define EZX_IRQ_USB1V EZX_IRQ(1) /* EMU */ +#define EZX_IRQ_HEADJACK EZX_IRQ(2) /* Audio connector */ +#define EZX_IRQ_MIC EZX_IRQ(3) /* Audio connector */ +#define EZX_IRQ_ADCDONE EZX_IRQ(4) +#define EZX_IRQ_TS EZX_IRQ(5) /* TS touch */ +#define EZX_IRQ_ADCDONE2 EZX_IRQ(6) /* TS x/y ADC ready */ +#define EZX_IRQ_WH EZX_IRQ(7) +#define EZX_IRQ_WL EZX_IRQ(8) +#define EZX_IRQ_ONOFF EZX_IRQ(9) +#define EZX_IRQ_ONOFF2 EZX_IRQ(10) +#define EZX_IRQ_MOBPORT EZX_IRQ(11) +#define EZX_IRQ_TODA EZX_IRQ(12) +#define EZX_IRQ_1HZ EZX_IRQ(13) +#define EZX_IRQ_MNEXB EZX_IRQ(14) +#define EZX_IRQ_ST EZX_IRQ(15) +#define EZX_IRQ_PC EZX_IRQ(16) +#define EZX_IRQ_SYSRST EZX_IRQ(17) +#define EZX_IRQ_SOFTRESET EZX_IRQ(18) +#define EZX_IRQ_EOL EZX_IRQ(19) +#define EZX_IRQ_CLK EZX_IRQ(20) +#define EZX_IRQ_WARM EZX_IRQ(21) + /* ITE8152 irqs */ /* add IT8152 IRQs beyond BOARD_END */ #ifdef CONFIG_PCI_HOST_ITE8152 Index: linux-2.6.24/arch/arm/mach-pxa/Kconfig =================================================================== --- linux-2.6.24.orig/arch/arm/mach-pxa/Kconfig +++ linux-2.6.24/arch/arm/mach-pxa/Kconfig @@ -139,6 +139,9 @@ This enables control code for the BP (baseband processor) found in Motorola's EZX smartphone platform. +config EZX_PCAP + bool "PCAP Support" + endif endmenu Index: linux-2.6.24/arch/arm/mach-pxa/Makefile =================================================================== --- linux-2.6.24.orig/arch/arm/mach-pxa/Makefile +++ linux-2.6.24/arch/arm/mach-pxa/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_PXA_EZX_A1200) += ezx-a1200.o obj-$(CONFIG_PXA_EZX_E6) += ezx-e6.o obj-$(CONFIG_EZX_BP) += ezx-bp.o +obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o # Support for blinky lights led-y := leds.o