diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-11 09:13:19 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-11 09:13:19 -0700 |
commit | 636d17427b1ef0e97bd9df9b3b0e0f314ff889d3 (patch) | |
tree | f573602c1a78e9140c36e220c47675b79af1c270 /drivers | |
parent | dd21e9bdff14a9882f2c485fe533c6ce64ea2675 (diff) | |
parent | 0b019a41553a919965bb02d07d54e3e6c57a796d (diff) |
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (226 commits)
ARM: 6323/1: cam60: don't use __init for cam60_spi_{flash_platform_data,partitions}
ARM: 6324/1: cam60: move cam60_spi_devices to .init.data
ARM: 6322/1: imx/pca100: Fix name of spi platform data
ARM: 6321/1: fix syntax error in main Kconfig file
ARM: 6297/1: move U300 timer to dynamic clock lookup
ARM: 6296/1: clock U300 intcon and timer properly
ARM: 6295/1: fix U300 apb_pclk split
ARM: 6306/1: fix inverted MMC card detect in U300
ARM: 6299/1: errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID
ARM: 6294/1: etm: do a dummy read from OSSRR during initialization
ARM: 6292/1: coresight: add ETM management registers
ARM: 6288/1: ftrace: document mcount formats
ARM: 6287/1: ftrace: clean up mcount assembly indentation
ARM: 6286/1: fix Thumb-2 decompressor broken by "Auto calculate ZRELADDR"
ARM: 6281/1: video/imxfb.c: allow usage without BACKLIGHT_CLASS_DEVICE
ARM: 6280/1: imx: Fix build failure when including <mach/gpio.h> without <linux/spinlock.h>
ARM: S5PV210: Fix on missing s3c-sdhci card detection method for hsmmc3
ARM: S5P: Fix on missing S5P_DEV_FIMC in plat-s5p/Kconfig
ARM: S5PV210: Override FIMC driver name on Aquila board
ARM: S5PC100: enable FIMC on SMDKC100
...
Fix up conflicts in arch/arm/mach-{s5pc100,s5pv210}/cpu.c due to
different subsystem 'setname' calls, and trivial port types in
include/linux/serial_core.h
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/Kconfig | 11 | ||||
-rw-r--r-- | drivers/ata/Makefile | 2 | ||||
-rw-r--r-- | drivers/ata/pata_pxa.c | 411 | ||||
-rw-r--r-- | drivers/dma/Kconfig | 2 | ||||
-rw-r--r-- | drivers/dma/shdma.c | 8 | ||||
-rw-r--r-- | drivers/i2c/busses/Kconfig | 13 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sh_mobile.c | 121 | ||||
-rw-r--r-- | drivers/net/irda/sh_irda.c | 6 | ||||
-rw-r--r-- | drivers/pcmcia/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pcmcia/Makefile | 1 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_balloon3.c | 158 | ||||
-rw-r--r-- | drivers/power/wm97xx_battery.c | 16 | ||||
-rw-r--r-- | drivers/rtc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/rtc/rtc-s3c.c | 44 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 4 | ||||
-rw-r--r-- | drivers/serial/s5pv210.c | 8 | ||||
-rw-r--r-- | drivers/serial/samsung.c | 9 | ||||
-rw-r--r-- | drivers/serial/sh-sci.c | 42 | ||||
-rw-r--r-- | drivers/serial/sh-sci.h | 29 | ||||
-rw-r--r-- | drivers/sh/Makefile | 5 | ||||
-rw-r--r-- | drivers/sh/clk-cpg.c | 58 | ||||
-rw-r--r-- | drivers/video/Kconfig | 15 | ||||
-rw-r--r-- | drivers/video/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/imxfb.c | 19 | ||||
-rw-r--r-- | drivers/video/sh_mipi_dsi.c | 505 | ||||
-rw-r--r-- | drivers/video/sh_mobile_hdmi.c | 1028 | ||||
-rw-r--r-- | drivers/video/sh_mobile_lcdcfb.c | 196 |
27 files changed, 2579 insertions, 145 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 8fae6afd6a3..65e3e270837 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -651,6 +651,17 @@ config PATA_VIA If unsure, say N. +config PATA_PXA + tristate "PXA DMA-capable PATA support" + depends on ARCH_PXA + help + This option enables support for harddrive attached to PXA CPU's bus. + + NOTE: This driver utilizes PXA DMA controller, in case your hardware + is not capable of doing MWDMA, use pata_platform instead. + + If unsure, say N. + config PATA_WINBOND tristate "Winbond SL82C105 PATA support" depends on PCI diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 6540632bda0..158eaa961b1 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -91,6 +91,8 @@ obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o obj-$(CONFIG_PATA_SAMSUNG_CF) += pata_samsung_cf.o obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o +obj-$(CONFIG_PATA_PXA) += pata_pxa.o + # Should be last but two libata driver obj-$(CONFIG_PATA_ACPI) += pata_acpi.o # Should be last but one libata driver diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c new file mode 100644 index 00000000000..1898c6ed4b4 --- /dev/null +++ b/drivers/ata/pata_pxa.c @@ -0,0 +1,411 @@ +/* + * Generic PXA PATA driver + * + * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/blkdev.h> +#include <linux/ata.h> +#include <linux/libata.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/slab.h> +#include <linux/completion.h> + +#include <scsi/scsi_host.h> + +#include <mach/pxa2xx-regs.h> +#include <mach/pata_pxa.h> +#include <mach/dma.h> + +#define DRV_NAME "pata_pxa" +#define DRV_VERSION "0.1" + +struct pata_pxa_data { + uint32_t dma_channel; + struct pxa_dma_desc *dma_desc; + dma_addr_t dma_desc_addr; + uint32_t dma_desc_id; + + /* DMA IO physical address */ + uint32_t dma_io_addr; + /* PXA DREQ<0:2> pin selector */ + uint32_t dma_dreq; + /* DMA DCSR register value */ + uint32_t dma_dcsr; + + struct completion dma_done; +}; + +/* + * Setup the DMA descriptors. The size is transfer capped at 4k per descriptor, + * if the transfer is longer, it is split into multiple chained descriptors. + */ +static void pxa_load_dmac(struct scatterlist *sg, struct ata_queued_cmd *qc) +{ + struct pata_pxa_data *pd = qc->ap->private_data; + + uint32_t cpu_len, seg_len; + dma_addr_t cpu_addr; + + cpu_addr = sg_dma_address(sg); + cpu_len = sg_dma_len(sg); + + do { + seg_len = (cpu_len > 0x1000) ? 0x1000 : cpu_len; + + pd->dma_desc[pd->dma_desc_id].ddadr = pd->dma_desc_addr + + ((pd->dma_desc_id + 1) * sizeof(struct pxa_dma_desc)); + + pd->dma_desc[pd->dma_desc_id].dcmd = DCMD_BURST32 | + DCMD_WIDTH2 | (DCMD_LENGTH & seg_len); + + if (qc->tf.flags & ATA_TFLAG_WRITE) { + pd->dma_desc[pd->dma_desc_id].dsadr = cpu_addr; + pd->dma_desc[pd->dma_desc_id].dtadr = pd->dma_io_addr; + pd->dma_desc[pd->dma_desc_id].dcmd |= DCMD_INCSRCADDR | + DCMD_FLOWTRG; + } else { + pd->dma_desc[pd->dma_desc_id].dsadr = pd->dma_io_addr; + pd->dma_desc[pd->dma_desc_id].dtadr = cpu_addr; + pd->dma_desc[pd->dma_desc_id].dcmd |= DCMD_INCTRGADDR | + DCMD_FLOWSRC; + } + + cpu_len -= seg_len; + cpu_addr += seg_len; + pd->dma_desc_id++; + + } while (cpu_len); + + /* Should not happen */ + if (seg_len & 0x1f) + DALGN |= (1 << pd->dma_dreq); +} + +/* + * Prepare taskfile for submission. + */ +static void pxa_qc_prep(struct ata_queued_cmd *qc) +{ + struct pata_pxa_data *pd = qc->ap->private_data; + int si = 0; + struct scatterlist *sg; + + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) + return; + + pd->dma_desc_id = 0; + + DCSR(pd->dma_channel) = 0; + DALGN &= ~(1 << pd->dma_dreq); + + for_each_sg(qc->sg, sg, qc->n_elem, si) + pxa_load_dmac(sg, qc); + + pd->dma_desc[pd->dma_desc_id - 1].ddadr = DDADR_STOP; + + /* Fire IRQ only at the end of last block */ + pd->dma_desc[pd->dma_desc_id - 1].dcmd |= DCMD_ENDIRQEN; + + DDADR(pd->dma_channel) = pd->dma_desc_addr; + DRCMR(pd->dma_dreq) = DRCMR_MAPVLD | pd->dma_channel; + +} + +/* + * Configure the DMA controller, load the DMA descriptors, but don't start the + * DMA controller yet. Only issue the ATA command. + */ +static void pxa_bmdma_setup(struct ata_queued_cmd *qc) +{ + qc->ap->ops->sff_exec_command(qc->ap, &qc->tf); +} + +/* + * Execute the DMA transfer. + */ +static void pxa_bmdma_start(struct ata_queued_cmd *qc) +{ + struct pata_pxa_data *pd = qc->ap->private_data; + init_completion(&pd->dma_done); + DCSR(pd->dma_channel) = DCSR_RUN; +} + +/* + * Wait until the DMA transfer completes, then stop the DMA controller. + */ +static void pxa_bmdma_stop(struct ata_queued_cmd *qc) +{ + struct pata_pxa_data *pd = qc->ap->private_data; + + if ((DCSR(pd->dma_channel) & DCSR_RUN) && + wait_for_completion_timeout(&pd->dma_done, HZ)) + dev_err(qc->ap->dev, "Timeout waiting for DMA completion!"); + + DCSR(pd->dma_channel) = 0; +} + +/* + * Read DMA status. The bmdma_stop() will take care of properly finishing the + * DMA transfer so we always have DMA-complete interrupt here. + */ +static unsigned char pxa_bmdma_status(struct ata_port *ap) +{ + struct pata_pxa_data *pd = ap->private_data; + unsigned char ret = ATA_DMA_INTR; + + if (pd->dma_dcsr & DCSR_BUSERR) + ret |= ATA_DMA_ERR; + + return ret; +} + +/* + * No IRQ register present so we do nothing. + */ +static void pxa_irq_clear(struct ata_port *ap) +{ +} + +/* + * Check for ATAPI DMA. ATAPI DMA is unsupported by this driver. It's still + * unclear why ATAPI has DMA issues. + */ +static int pxa_check_atapi_dma(struct ata_queued_cmd *qc) +{ + return -EOPNOTSUPP; +} + +static struct scsi_host_template pxa_ata_sht = { + ATA_BMDMA_SHT(DRV_NAME), +}; + +static struct ata_port_operations pxa_ata_port_ops = { + .inherits = &ata_bmdma_port_ops, + .cable_detect = ata_cable_40wire, + + .bmdma_setup = pxa_bmdma_setup, + .bmdma_start = pxa_bmdma_start, + .bmdma_stop = pxa_bmdma_stop, + .bmdma_status = pxa_bmdma_status, + + .check_atapi_dma = pxa_check_atapi_dma, + + .sff_irq_clear = pxa_irq_clear, + + .qc_prep = pxa_qc_prep, +}; + +/* + * DMA interrupt handler. + */ +static void pxa_ata_dma_irq(int dma, void *port) +{ + struct ata_port *ap = port; + struct pata_pxa_data *pd = ap->private_data; + + pd->dma_dcsr = DCSR(dma); + DCSR(dma) = pd->dma_dcsr; + + if (pd->dma_dcsr & DCSR_STOPSTATE) + complete(&pd->dma_done); +} + +static int __devinit pxa_ata_probe(struct platform_device *pdev) +{ + struct ata_host *host; + struct ata_port *ap; + struct pata_pxa_data *data; + struct resource *cmd_res; + struct resource *ctl_res; + struct resource *dma_res; + struct resource *irq_res; + struct pata_pxa_pdata *pdata = pdev->dev.platform_data; + int ret = 0; + + /* + * Resource validation, three resources are needed: + * - CMD port base address + * - CTL port base address + * - DMA port base address + * - IRQ pin + */ + if (pdev->num_resources != 4) { + dev_err(&pdev->dev, "invalid number of resources\n"); + return -EINVAL; + } + + /* + * CMD port base address + */ + cmd_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(cmd_res == NULL)) + return -EINVAL; + + /* + * CTL port base address + */ + ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (unlikely(ctl_res == NULL)) + return -EINVAL; + + /* + * DMA port base address + */ + dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (unlikely(dma_res == NULL)) + return -EINVAL; + + /* + * IRQ pin + */ + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (unlikely(irq_res == NULL)) + return -EINVAL; + + /* + * Allocate the host + */ + host = ata_host_alloc(&pdev->dev, 1); + if (!host) + return -ENOMEM; + + ap = host->ports[0]; + ap->ops = &pxa_ata_port_ops; + ap->pio_mask = ATA_PIO4; + ap->mwdma_mask = ATA_MWDMA2; + ap->flags = ATA_FLAG_MMIO; + + ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, cmd_res->start, + resource_size(cmd_res)); + ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start, + resource_size(ctl_res)); + ap->ioaddr.bmdma_addr = devm_ioremap(&pdev->dev, dma_res->start, + resource_size(dma_res)); + + /* + * Adjust register offsets + */ + ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; + ap->ioaddr.data_addr = ap->ioaddr.cmd_addr + + (ATA_REG_DATA << pdata->reg_shift); + ap->ioaddr.error_addr = ap->ioaddr.cmd_addr + + (ATA_REG_ERR << pdata->reg_shift); + ap->ioaddr.feature_addr = ap->ioaddr.cmd_addr + + (ATA_REG_FEATURE << pdata->reg_shift); + ap->ioaddr.nsect_addr = ap->ioaddr.cmd_addr + + (ATA_REG_NSECT << pdata->reg_shift); + ap->ioaddr.lbal_addr = ap->ioaddr.cmd_addr + + (ATA_REG_LBAL << pdata->reg_shift); + ap->ioaddr.lbam_addr = ap->ioaddr.cmd_addr + + (ATA_REG_LBAM << pdata->reg_shift); + ap->ioaddr.lbah_addr = ap->ioaddr.cmd_addr + + (ATA_REG_LBAH << pdata->reg_shift); + ap->ioaddr.device_addr = ap->ioaddr.cmd_addr + + (ATA_REG_DEVICE << pdata->reg_shift); + ap->ioaddr.status_addr = ap->ioaddr.cmd_addr + + (ATA_REG_STATUS << pdata->reg_shift); + ap->ioaddr.command_addr = ap->ioaddr.cmd_addr + + (ATA_REG_CMD << pdata->reg_shift); + + /* + * Allocate and load driver's internal data structure + */ + data = devm_kzalloc(&pdev->dev, sizeof(struct pata_pxa_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + ap->private_data = data; + data->dma_dreq = pdata->dma_dreq; + data->dma_io_addr = dma_res->start; + + /* + * Allocate space for the DMA descriptors + */ + data->dma_desc = dmam_alloc_coherent(&pdev->dev, PAGE_SIZE, + &data->dma_desc_addr, GFP_KERNEL); + if (!data->dma_desc) + return -EINVAL; + + /* + * Request the DMA channel + */ + data->dma_channel = pxa_request_dma(DRV_NAME, DMA_PRIO_LOW, + pxa_ata_dma_irq, ap); + if (data->dma_channel < 0) + return -EBUSY; + + /* + * Stop and clear the DMA channel + */ + DCSR(data->dma_channel) = 0; + + /* + * Activate the ATA host + */ + ret = ata_host_activate(host, irq_res->start, ata_sff_interrupt, + pdata->irq_flags, &pxa_ata_sht); + if (ret) + pxa_free_dma(data->dma_channel); + + return ret; +} + +static int __devexit pxa_ata_remove(struct platform_device *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + struct pata_pxa_data *data = host->ports[0]->private_data; + + pxa_free_dma(data->dma_channel); + + ata_host_detach(host); + + return 0; +} + +static struct platform_driver pxa_ata_driver = { + .probe = pxa_ata_probe, + .remove = __devexit_p(pxa_ata_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init pxa_ata_init(void) +{ + return platform_driver_register(&pxa_ata_driver); +} + +static void __exit pxa_ata_exit(void) +{ + platform_driver_unregister(&pxa_ata_driver); +} + +module_init(pxa_ata_init); +module_exit(pxa_ata_exit); + +MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); +MODULE_DESCRIPTION("DMA-capable driver for PATA on PXA CPU"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index fed57634b6c..9520cf02edc 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -141,7 +141,7 @@ config TXX9_DMAC config SH_DMAE tristate "Renesas SuperH DMAC support" - depends on SUPERH && SH_DMA + depends on (SUPERH && SH_DMA) || (ARM && ARCH_SHMOBILE) depends on !SH_DMA_API select DMA_ENGINE help diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index a2a519fd2a2..fb64cf36ba6 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -816,7 +816,7 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data) return ret; } -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) static irqreturn_t sh_dmae_err(int irq, void *data) { struct sh_dmae_device *shdev = (struct sh_dmae_device *)data; @@ -1057,7 +1057,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) /* Default transfer size of 32 bytes requires 32-byte alignment */ shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE; -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (!chanirq_res) @@ -1082,7 +1082,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) #else chanirq_res = errirq_res; -#endif /* CONFIG_CPU_SH4 */ +#endif /* CONFIG_CPU_SH4 || CONFIG_ARCH_SHMOBILE */ if (chanirq_res->start == chanirq_res->end && !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { @@ -1129,7 +1129,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) chan_probe_err: sh_dmae_chan_remove(shdev); eirqres: -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) free_irq(errirq, shdev); eirq_err: #endif diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index bceafbfa726..15a9702e294 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -521,12 +521,19 @@ config I2C_PXA_SLAVE is necessary for systems where the PXA may be a target on the I2C bus. +config HAVE_S3C2410_I2C + bool + help + This will include I2C support for Samsung SoCs. If you want to + include I2C support for any machine, kindly select this in the + respective Kconfig file. + config I2C_S3C2410 tristate "S3C2410 I2C Driver" - depends on ARCH_S3C2410 || ARCH_S3C64XX + depends on HAVE_S3C2410_I2C help Say Y here to include support for I2C controller in the - Samsung S3C2410 based System-on-Chip devices. + Samsung SoCs. config I2C_S6000 tristate "S6000 I2C support" @@ -549,7 +556,7 @@ config I2C_SH7760 config I2C_SH_MOBILE tristate "SuperH Mobile I2C Controller" - depends on SUPERH + depends on SUPERH || ARCH_SHMOBILE help If you say yes to this option, support will be included for the built-in I2C interface on the Renesas SH-Mobile processor. diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index ffb405d7c6f..598c49acaeb 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -119,8 +119,10 @@ struct sh_mobile_i2c_data { struct i2c_adapter adap; struct clk *clk; + u_int8_t icic; u_int8_t iccl; u_int8_t icch; + u_int8_t flags; spinlock_t lock; wait_queue_head_t wait; @@ -129,15 +131,17 @@ struct sh_mobile_i2c_data { int sr; }; +#define IIC_FLAG_HAS_ICIC67 (1 << 0) + #define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ /* Register offsets */ -#define ICDR(pd) (pd->reg + 0x00) -#define ICCR(pd) (pd->reg + 0x04) -#define ICSR(pd) (pd->reg + 0x08) -#define ICIC(pd) (pd->reg + 0x0c) -#define ICCL(pd) (pd->reg + 0x10) -#define ICCH(pd) (pd->reg + 0x14) +#define ICDR 0x00 +#define ICCR 0x04 +#define ICSR 0x08 +#define ICIC 0x0c +#define ICCL 0x10 +#define ICCH 0x14 /* Register bits */ #define ICCR_ICE 0x80 @@ -155,11 +159,32 @@ struct sh_mobile_i2c_data { #define ICSR_WAIT 0x02 #define ICSR_DTE 0x01 +#define ICIC_ICCLB8 0x80 +#define ICIC_ICCHB8 0x40 #define ICIC_ALE 0x08 #define ICIC_TACKE 0x04 #define ICIC_WAITE 0x02 #define ICIC_DTEE 0x01 +static void iic_wr(struct sh_mobile_i2c_data *pd, int offs, unsigned char data) +{ + if (offs == ICIC) + data |= pd->icic; + + iowrite8(data, pd->reg + offs); +} + +static unsigned char iic_rd(struct sh_mobile_i2c_data *pd, int offs) +{ + return ioread8(pd->reg + offs); +} + +static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs, + unsigned char set, unsigned char clr) +{ + iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr); +} + static void activate_ch(struct sh_mobile_i2c_data *pd) { unsigned long i2c_clk; @@ -187,6 +212,14 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) else pd->iccl = (u_int8_t)(num/denom); + /* one more bit of ICCL in ICIC */ + if (pd->flags & IIC_FLAG_HAS_ICIC67) { + if ((num/denom) > 0xff) + pd->icic |= ICIC_ICCLB8; + else + pd->icic &= ~ICIC_ICCLB8; + } + /* Calculate the value for icch. From the data sheet: icch = (p clock / transfer rate) * (H / (L + H)) */ num = i2c_clk * 4; @@ -196,25 +229,33 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) else pd->icch = (u_int8_t)(num/denom); + /* one more bit of ICCH in ICIC */ + if (pd->flags & IIC_FLAG_HAS_ICIC67) { + if ((num/denom) > 0xff) + pd->icic |= ICIC_ICCHB8; + else + pd->icic &= ~ICIC_ICCHB8; + } + /* Enable channel and configure rx ack */ - iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); + iic_set_clr(pd, ICCR, ICCR_ICE, 0); /* Mask all interrupts */ - iowrite8(0, ICIC(pd)); + iic_wr(pd, ICIC, 0); /* Set the clock */ - iowrite8(pd->iccl, ICCL(pd)); - iowrite8(pd->icch, ICCH(pd)); + iic_wr(pd, ICCL, pd->iccl); + iic_wr(pd, ICCH, pd->icch); } static void deactivate_ch(struct sh_mobile_i2c_data *pd) { /* Clear/disable interrupts */ - iowrite8(0, ICSR(pd)); - iowrite8(0, ICIC(pd)); + iic_wr(pd, ICSR, 0); + iic_wr(pd, ICIC, 0); /* Disable channel */ - iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); + iic_set_clr(pd, ICCR, 0, ICCR_ICE); /* Disable clock and mark device as idle */ clk_disable(pd->clk); @@ -233,35 +274,35 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, switch (op) { case OP_START: /* issue start and trigger DTE interrupt */ - iowrite8(0x94, ICCR(pd)); + iic_wr(pd, ICCR, 0x94); break; case OP_TX_FIRST: /* disable DTE interrupt and write data */ - iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE, ICIC(pd)); - iowrite8(data, ICDR(pd)); + iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE); + iic_wr(pd, ICDR, data); break; case OP_TX: /* write data */ - iowrite8(data, ICDR(pd)); + iic_wr(pd, ICDR, data); break; case OP_TX_STOP: /* write data and issue a stop afterwards */ - iowrite8(data, ICDR(pd)); - iowrite8(0x90, ICCR(pd)); + iic_wr(pd, ICDR, data); + iic_wr(pd, ICCR, 0x90); break; case OP_TX_TO_RX: /* select read mode */ - iowrite8(0x81, ICCR(pd)); + iic_wr(pd, ICCR, 0x81); break; case OP_RX: /* just read data */ - ret = ioread8(ICDR(pd)); + ret = iic_rd(pd, ICDR); break; case OP_RX_STOP: /* enable DTE interrupt, issue stop */ - iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, - ICIC(pd)); - iowrite8(0xc0, ICCR(pd)); + iic_wr(pd, ICIC, + ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); + iic_wr(pd, ICCR, 0xc0); break; case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ - iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, - ICIC(pd)); - ret = ioread8(ICDR(pd)); - iowrite8(0xc0, ICCR(pd)); + iic_wr(pd, ICIC, + ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); + ret = iic_rd(pd, ICDR); + iic_wr(pd, ICCR, 0xc0); break; } @@ -367,7 +408,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) unsigned char sr; int wakeup; - sr = ioread8(ICSR(pd)); + sr = iic_rd(pd, ICSR); pd->sr |= sr; /* remember state */ dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr, @@ -376,7 +417,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) if (sr & (ICSR_AL | ICSR_TACK)) { /* don't interrupt transaction - continue to issue stop */ - iowrite8(sr & ~(ICSR_AL | ICSR_TACK), ICSR(pd)); + iic_wr(pd, ICSR, sr & ~(ICSR_AL | ICSR_TACK)); wakeup = 0; } else if (pd->msg->flags & I2C_M_RD) wakeup = sh_mobile_i2c_isr_rx(pd); @@ -384,7 +425,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) wakeup = sh_mobile_i2c_isr_tx(pd); if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */ - iowrite8(sr & ~ICSR_WAIT, ICSR(pd)); + iic_wr(pd, ICSR, sr & ~ICSR_WAIT); if (wakeup) { pd->sr |= SW_DONE; @@ -402,21 +443,21 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg) } /* Initialize channel registers */ - iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); + iic_set_clr(pd, ICCR, 0, ICCR_ICE); /* Enable channel and configure rx ack */ - iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); + iic_set_clr(pd, ICCR, ICCR_ICE, 0); /* Set the clock */ - iowrite8(pd->iccl, ICCL(pd)); - iowrite8(pd->icch, ICCH(pd)); + iic_wr(pd, ICCL, pd->iccl); + iic_wr(pd, ICCH, pd->icch); pd->msg = usr_msg; pd->pos = -1; pd->sr = 0; /* Enable all interrupts to begin with */ - iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE | ICIC_DTEE, ICIC(pd)); + iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); return 0; } @@ -451,7 +492,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, retry_count = 1000; again: - val = ioread8(ICSR(pd)); + val = iic_rd(pd, ICSR); dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr); @@ -576,6 +617,12 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) goto err_irq; } + /* The IIC blocks on SH-Mobile ARM processors + * come with two new bits in ICIC. + */ + if (size > 0x17) + pd->flags |= IIC_FLAG_HAS_ICIC67; + /* Enable Runtime PM for this device. * * Also tell the Runtime PM core to ignore children diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c index edd5666f0ff..9e3f4f54281 100644 --- a/drivers/net/irda/sh_irda.c +++ b/drivers/net/irda/sh_irda.c @@ -748,7 +748,6 @@ static int __devinit sh_irda_probe(struct platform_device *pdev) struct net_device *ndev; struct sh_irda_self *self; struct resource *res; - char clk_name[8]; int irq; int err = -ENOMEM; @@ -775,10 +774,9 @@ static int __devinit sh_irda_probe(struct platform_device *pdev) if (err) goto err_mem_2; - snprintf(clk_name, sizeof(clk_name), "irda%d", pdev->id); - self->clk = clk_get(&pdev->dev, clk_name); + self->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(self->clk)) { - dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); + dev_err(&pdev->dev, "cannot get irda clock\n"); goto err_mem_3; } diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index c988514eb55..c80a7a6e769 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -215,7 +215,7 @@ config PCMCIA_PXA2XX depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ - || MACH_VPAC270) + || MACH_VPAC270 || MACH_BALLOON3) select PCMCIA_SOC_COMMON help Say Y here to include support for the PXA2xx PCMCIA controller diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 7a2b1604bf1..8d9386a22eb 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -69,6 +69,7 @@ pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o +pxa2xx-obj-$(CONFIG_MACH_BALLOON3) += pxa2xx_balloon3.o obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) diff --git a/drivers/pcmcia/pxa2xx_balloon3.c b/drivers/pcmcia/pxa2xx_balloon3.c new file mode 100644 index 00000000000..dbbdd006320 --- /dev/null +++ b/drivers/pcmcia/pxa2xx_balloon3.c @@ -0,0 +1,158 @@ +/* + * linux/drivers/pcmcia/pxa2xx_balloon3.c + * + * Balloon3 PCMCIA specific routines. + * + * Author: Nick Bane + * Created: June, 2006 + * Copyright: Toby Churchill Ltd + * Derived from pxa2xx_mainstone.c, by Nico Pitre + * + * Various modification by Marek Vasut <marek.vasut@gmail.com> + * + * 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 <linux/module.h> +#include <linux/gpio.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/irq.h> |