diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-14 16:42:43 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-14 16:42:43 -0400 |
| commit | 2cf4d4514d5b43c1f3b64bd0ec8b9853bde8f1dc (patch) | |
| tree | e35a625496acc6ac852846d40b8851186b9d1ac4 /drivers | |
| parent | 44b7532b8b464f606053562400719c9c21276037 (diff) | |
| parent | ce53895a5d24e0ee19fb92f56c17323fb4c9ab27 (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: (417 commits)
MAINTAINERS: EB110ATX is not ebsa110
MAINTAINERS: update Eric Miao's email address and status
fb: add support of LCD display controller on pxa168/910 (base layer)
[ARM] 5552/1: ep93xx get_uart_rate(): use EP93XX_SYSCON_PWRCNT and EP93XX_SYSCON_PWRCN
[ARM] pxa/sharpsl_pm: zaurus needs generic pxa suspend/resume routines
[ARM] 5544/1: Trust PrimeCell resource sizes
[ARM] pxa/sharpsl_pm: cleanup of gpio-related code.
[ARM] pxa/sharpsl_pm: drop set_irq_type calls
[ARM] pxa/sharpsl_pm: merge pxa-specific code into generic one
[ARM] pxa/sharpsl_pm: merge the two sharpsl_pm.c since it's now pxa specific
[ARM] sa1100: remove unused collie_pm.c
[ARM] pxa: fix the conflicting non-static declarations of global_gpios[]
[ARM] 5550/1: Add default configure file for w90p910 platform
[ARM] 5549/1: Add clock api for w90p910 platform.
[ARM] 5548/1: Add gpio api for w90p910 platform
[ARM] 5551/1: Add multi-function pin api for w90p910 platform.
[ARM] Make ARM_VIC_NR depend on ARM_VIC
[ARM] 5546/1: ARM PL022 SSP/SPI driver v3
ARM: OMAP4: SMP: Update defconfig for OMAP4430
ARM: OMAP4: SMP: Enable SMP support for OMAP4430
...
Diffstat (limited to 'drivers')
43 files changed, 4145 insertions, 178 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 9120717c0701..2aa1908e5ce0 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
| @@ -535,6 +535,15 @@ config PATA_OPTIDMA | |||
| 535 | 535 | ||
| 536 | If unsure, say N. | 536 | If unsure, say N. |
| 537 | 537 | ||
| 538 | config PATA_PALMLD | ||
| 539 | tristate "Palm LifeDrive PATA support" | ||
| 540 | depends on MACH_PALMLD | ||
| 541 | help | ||
| 542 | This option enables support for Palm LifeDrive's internal ATA | ||
| 543 | port via the new ATA layer. | ||
| 544 | |||
| 545 | If unsure, say N. | ||
| 546 | |||
| 538 | config PATA_PCMCIA | 547 | config PATA_PCMCIA |
| 539 | tristate "PCMCIA PATA support" | 548 | tristate "PCMCIA PATA support" |
| 540 | depends on PCMCIA | 549 | depends on PCMCIA |
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 7f1ecf99528c..1558059874f0 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile | |||
| @@ -50,6 +50,7 @@ obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o | |||
| 50 | obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o | 50 | obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o |
| 51 | obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o | 51 | obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o |
| 52 | obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o | 52 | obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o |
| 53 | obj-$(CONFIG_PATA_PALMLD) += pata_palmld.o | ||
| 53 | obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o | 54 | obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o |
| 54 | obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o | 55 | obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o |
| 55 | obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o | 56 | obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o |
diff --git a/drivers/ata/pata_palmld.c b/drivers/ata/pata_palmld.c new file mode 100644 index 000000000000..11fb4ccc74b4 --- /dev/null +++ b/drivers/ata/pata_palmld.c | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | /* | ||
| 2 | * drivers/ata/pata_palmld.c | ||
| 3 | * | ||
| 4 | * Driver for IDE channel in Palm LifeDrive | ||
| 5 | * | ||
| 6 | * Based on research of: | ||
| 7 | * Alex Osborne <ato@meshy.org> | ||
| 8 | * | ||
| 9 | * Rewrite for mainline: | ||
| 10 | * Marek Vasut <marek.vasut@gmail.com> | ||
| 11 | * | ||
| 12 | * Rewritten version based on pata_ixp4xx_cf.c: | ||
| 13 | * ixp4xx PATA/Compact Flash driver | ||
| 14 | * Copyright (C) 2006-07 Tower Technologies | ||
| 15 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 16 | * | ||
| 17 | * This program is free software; you can redistribute it and/or modify | ||
| 18 | * it under the terms of the GNU General Public License version 2 as | ||
| 19 | * published by the Free Software Foundation. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/libata.h> | ||
| 26 | #include <linux/irq.h> | ||
| 27 | #include <linux/platform_device.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | #include <linux/gpio.h> | ||
| 30 | |||
| 31 | #include <scsi/scsi_host.h> | ||
| 32 | #include <mach/palmld.h> | ||
| 33 | |||
| 34 | #define DRV_NAME "pata_palmld" | ||
| 35 | |||
| 36 | static struct scsi_host_template palmld_sht = { | ||
| 37 | ATA_PIO_SHT(DRV_NAME), | ||
| 38 | }; | ||
| 39 | |||
| 40 | static struct ata_port_operations palmld_port_ops = { | ||
| 41 | .inherits = &ata_sff_port_ops, | ||
| 42 | .sff_data_xfer = ata_sff_data_xfer_noirq, | ||
| 43 | .cable_detect = ata_cable_40wire, | ||
| 44 | }; | ||
| 45 | |||
| 46 | static __devinit int palmld_pata_probe(struct platform_device *pdev) | ||
| 47 | { | ||
| 48 | struct ata_host *host; | ||
| 49 | struct ata_port *ap; | ||
| 50 | void __iomem *mem; | ||
| 51 | int ret; | ||
| 52 | |||
| 53 | /* allocate host */ | ||
| 54 | host = ata_host_alloc(&pdev->dev, 1); | ||
| 55 | if (!host) | ||
| 56 | return -ENOMEM; | ||
| 57 | |||
| 58 | /* remap drive's physical memory address */ | ||
| 59 | mem = devm_ioremap(&pdev->dev, PALMLD_IDE_PHYS, 0x1000); | ||
| 60 | if (!mem) | ||
| 61 | return -ENOMEM; | ||
| 62 | |||
| 63 | /* request and activate power GPIO, IRQ GPIO */ | ||
| 64 | ret = gpio_request(GPIO_NR_PALMLD_IDE_PWEN, "HDD PWR"); | ||
| 65 | if (ret) | ||
| 66 | goto err1; | ||
| 67 | ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_PWEN, 1); | ||
| 68 | if (ret) | ||
| 69 | goto err2; | ||
| 70 | |||
| 71 | ret = gpio_request(GPIO_NR_PALMLD_IDE_RESET, "HDD RST"); | ||
| 72 | if (ret) | ||
| 73 | goto err2; | ||
| 74 | ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_RESET, 0); | ||
| 75 | if (ret) | ||
| 76 | goto err3; | ||
| 77 | |||
| 78 | /* reset the drive */ | ||
| 79 | gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 0); | ||
| 80 | msleep(30); | ||
| 81 | gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 1); | ||
| 82 | msleep(30); | ||
| 83 | |||
| 84 | /* setup the ata port */ | ||
| 85 | ap = host->ports[0]; | ||
| 86 | ap->ops = &palmld_port_ops; | ||
| 87 | ap->pio_mask = ATA_PIO4; | ||
| 88 | ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_PIO_POLLING; | ||
| 89 | |||
| 90 | /* memory mapping voodoo */ | ||
| 91 | ap->ioaddr.cmd_addr = mem + 0x10; | ||
| 92 | ap->ioaddr.altstatus_addr = mem + 0xe; | ||
| 93 | ap->ioaddr.ctl_addr = mem + 0xe; | ||
| 94 | |||
| 95 | /* start the port */ | ||
| 96 | ata_sff_std_ports(&ap->ioaddr); | ||
| 97 | |||
| 98 | /* activate host */ | ||
| 99 | return ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING, | ||
| 100 | &palmld_sht); | ||
| 101 | |||
| 102 | err3: | ||
| 103 | gpio_free(GPIO_NR_PALMLD_IDE_RESET); | ||
| 104 | err2: | ||
| 105 | gpio_free(GPIO_NR_PALMLD_IDE_PWEN); | ||
| 106 | err1: | ||
| 107 | return ret; | ||
| 108 | } | ||
| 109 | |||
| 110 | static __devexit int palmld_pata_remove(struct platform_device *dev) | ||
| 111 | { | ||
| 112 | struct ata_host *host = platform_get_drvdata(dev); | ||
| 113 | |||
| 114 | ata_host_detach(host); | ||
| 115 | |||
| 116 | /* power down the HDD */ | ||
| 117 | gpio_set_value(GPIO_NR_PALMLD_IDE_PWEN, 0); | ||
| 118 | |||
| 119 | gpio_free(GPIO_NR_PALMLD_IDE_RESET); | ||
| 120 | gpio_free(GPIO_NR_PALMLD_IDE_PWEN); | ||
| 121 | |||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | static struct platform_driver palmld_pata_platform_driver = { | ||
| 126 | .driver = { | ||
| 127 | .name = DRV_NAME, | ||
| 128 | .owner = THIS_MODULE, | ||
| 129 | }, | ||
| 130 | .probe = palmld_pata_probe, | ||
| 131 | .remove = __devexit_p(palmld_pata_remove), | ||
| 132 | }; | ||
| 133 | |||
| 134 | static int __init palmld_pata_init(void) | ||
| 135 | { | ||
| 136 | return platform_driver_register(&palmld_pata_platform_driver); | ||
| 137 | } | ||
| 138 | |||
| 139 | static void __exit palmld_pata_exit(void) | ||
| 140 | { | ||
| 141 | platform_driver_unregister(&palmld_pata_platform_driver); | ||
| 142 | } | ||
| 143 | |||
| 144 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
| 145 | MODULE_DESCRIPTION("PalmLD PATA driver"); | ||
| 146 | MODULE_LICENSE("GPL"); | ||
| 147 | MODULE_ALIAS("platform:" DRV_NAME); | ||
| 148 | |||
| 149 | module_init(palmld_pata_init); | ||
| 150 | module_exit(palmld_pata_exit); | ||
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 9c00440dcf86..f4b3f7293feb 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
| @@ -148,3 +148,15 @@ config HW_RANDOM_VIRTIO | |||
| 148 | 148 | ||
| 149 | To compile this driver as a module, choose M here: the | 149 | To compile this driver as a module, choose M here: the |
| 150 | module will be called virtio-rng. If unsure, say N. | 150 | module will be called virtio-rng. If unsure, say N. |
| 151 | |||
| 152 | config HW_RANDOM_MXC_RNGA | ||
| 153 | tristate "Freescale i.MX RNGA Random Number Generator" | ||
| 154 | depends on HW_RANDOM && ARCH_HAS_RNGA | ||
| 155 | ---help--- | ||
| 156 | This driver provides kernel-side support for the Random Number | ||
| 157 | Generator hardware found on Freescale i.MX processors. | ||
| 158 | |||
| 159 | To compile this driver as a module, choose M here: the | ||
| 160 | module will be called mxc-rnga. | ||
| 161 | |||
| 162 | If unsure, say Y. | ||
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index e81d21a5f28f..fd1ecd2f6731 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
| @@ -15,3 +15,4 @@ obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o | |||
| 15 | obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o | 15 | obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o |
| 16 | obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o | 16 | obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o |
| 17 | obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o | 17 | obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o |
| 18 | obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o | ||
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c new file mode 100644 index 000000000000..187c6be80f43 --- /dev/null +++ b/drivers/char/hw_random/mxc-rnga.c | |||
| @@ -0,0 +1,247 @@ | |||
| 1 | /* | ||
| 2 | * RNG driver for Freescale RNGA | ||
| 3 | * | ||
| 4 | * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. | ||
| 5 | * Author: Alan Carvalho de Assis <acassis@gmail.com> | ||
| 6 | */ | ||
| 7 | |||
| 8 | /* | ||
| 9 | * The code contained herein is licensed under the GNU General Public | ||
| 10 | * License. You may obtain a copy of the GNU General Public License | ||
| 11 | * Version 2 or later at the following locations: | ||
| 12 | * | ||
| 13 | * http://www.opensource.org/licenses/gpl-license.html | ||
| 14 | * http://www.gnu.org/copyleft/gpl.html | ||
| 15 | * | ||
| 16 | * This driver is based on other RNG drivers. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/clk.h> | ||
| 23 | #include <linux/err.h> | ||
| 24 | #include <linux/ioport.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | #include <linux/hw_random.h> | ||
| 27 | #include <linux/io.h> | ||
| 28 | |||
| 29 | /* RNGA Registers */ | ||
| 30 | #define RNGA_CONTROL 0x00 | ||
| 31 | #define RNGA_STATUS 0x04 | ||
| 32 | #define RNGA_ENTROPY 0x08 | ||
| 33 | #define RNGA_OUTPUT_FIFO 0x0c | ||
| 34 | #define RNGA_MODE 0x10 | ||
| 35 | #define RNGA_VERIFICATION_CONTROL 0x14 | ||
| 36 | #define RNGA_OSC_CONTROL_COUNTER 0x18 | ||
| 37 | #define RNGA_OSC1_COUNTER 0x1c | ||
| 38 | #define RNGA_OSC2_COUNTER 0x20 | ||
| 39 | #define RNGA_OSC_COUNTER_STATUS 0x24 | ||
| 40 | |||
| 41 | /* RNGA Registers Range */ | ||
| 42 | #define RNG_ADDR_RANGE 0x28 | ||
| 43 | |||
| 44 | /* RNGA Control Register */ | ||
| 45 | #define RNGA_CONTROL_SLEEP 0x00000010 | ||
| 46 | #define RNGA_CONTROL_CLEAR_INT 0x00000008 | ||
| 47 | #define RNGA_CONTROL_MASK_INTS 0x00000004 | ||
| 48 | #define RNGA_CONTROL_HIGH_ASSURANCE 0x00000002 | ||
| 49 | #define RNGA_CONTROL_GO 0x00000001 | ||
| 50 | |||
| 51 | #define RNGA_STATUS_LEVEL_MASK 0x0000ff00 | ||
| 52 | |||
| 53 | /* RNGA Status Register */ | ||
| 54 | #define RNGA_STATUS_OSC_DEAD 0x80000000 | ||
| 55 | #define RNGA_STATUS_SLEEP 0x00000010 | ||
| 56 | #define RNGA_STATUS_ERROR_INT 0x00000008 | ||
| 57 | #define RNGA_STATUS_FIFO_UNDERFLOW 0x00000004 | ||
| 58 | #define RNGA_STATUS_LAST_READ_STATUS 0x00000002 | ||
| 59 | #define RNGA_STATUS_SECURITY_VIOLATION 0x00000001 | ||
| 60 | |||
| 61 | static struct platform_device *rng_dev; | ||
| 62 | |||
| 63 | static int mxc_rnga_data_present(struct hwrng *rng) | ||
| 64 | { | ||
| 65 | int level; | ||
| 66 | void __iomem *rng_base = (void __iomem *)rng->priv; | ||
| 67 | |||
| 68 | /* how many random numbers is in FIFO? [0-16] */ | ||
| 69 | level = ((__raw_readl(rng_base + RNGA_STATUS) & | ||
| 70 | RNGA_STATUS_LEVEL_MASK) >> 8); | ||
| 71 | |||
| 72 | return level > 0 ? 1 : 0; | ||
| 73 | } | ||
| 74 | |||
| 75 | static int mxc_rnga_data_read(struct hwrng *rng, u32 * data) | ||
| 76 | { | ||
| 77 | int err; | ||
| 78 | u32 ctrl; | ||
| 79 | void __iomem *rng_base = (void __iomem *)rng->priv; | ||
| 80 | |||
| 81 | /* retrieve a random number from FIFO */ | ||
| 82 | *data = __raw_readl(rng_base + RNGA_OUTPUT_FIFO); | ||
| 83 | |||
| 84 | /* some error while reading this random number? */ | ||
| 85 | err = __raw_readl(rng_base + RNGA_STATUS) & RNGA_STATUS_ERROR_INT; | ||
| 86 | |||
| 87 | /* if error: clear error interrupt, but doesn't return random number */ | ||
| 88 | if (err) { | ||
| 89 | dev_dbg(&rng_dev->dev, "Error while reading random number!\n"); | ||
| 90 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); | ||
| 91 | __raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT, | ||
| 92 | rng_base + RNGA_CONTROL); | ||
| 93 | return 0; | ||
| 94 | } else | ||
| 95 | return 4; | ||
| 96 | } | ||
| 97 | |||
| 98 | static int mxc_rnga_init(struct hwrng *rng) | ||
| 99 | { | ||
| 100 | u32 ctrl, osc; | ||
| 101 | void __iomem *rng_base = (void __iomem *)rng->priv; | ||
| 102 | |||
| 103 | /* wake up */ | ||
| 104 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); | ||
| 105 | __raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, rng_base + RNGA_CONTROL); | ||
| 106 | |||
| 107 | /* verify if oscillator is working */ | ||
| 108 | osc = __raw_readl(rng_base + RNGA_STATUS); | ||
| 109 | if (osc & RNGA_STATUS_OSC_DEAD) { | ||
| 110 | dev_err(&rng_dev->dev, "RNGA Oscillator is dead!\n"); | ||
| 111 | return -ENODEV; | ||
| 112 | } | ||
| 113 | |||
| 114 | /* go running */ | ||
| 115 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); | ||
| 116 | __raw_writel(ctrl | RNGA_CONTROL_GO, rng_base + RNGA_CONTROL); | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static void mxc_rnga_cleanup(struct hwrng *rng) | ||
| 122 | { | ||
| 123 | u32 ctrl; | ||
| 124 | void __iomem *rng_base = (void __iomem *)rng->priv; | ||
| 125 | |||
| 126 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); | ||
| 127 | |||
| 128 | /* stop rnga */ | ||
| 129 | __raw_writel(ctrl & ~RNGA_CONTROL_GO, rng_base + RNGA_CONTROL); | ||
| 130 | } | ||
| 131 | |||
| 132 | static struct hwrng mxc_rnga = { | ||
| 133 | .name = "mxc-rnga", | ||
| 134 | .init = mxc_rnga_init, | ||
| 135 | .cleanup = mxc_rnga_cleanup, | ||
| 136 | .data_present = mxc_rnga_data_present, | ||
| 137 | .data_read = mxc_rnga_data_read | ||
| 138 | }; | ||
| 139 | |||
| 140 | static int __init mxc_rnga_probe(struct platform_device *pdev) | ||
| 141 | { | ||
| 142 | int err = -ENODEV; | ||
| 143 | struct clk *clk; | ||
| 144 | struct resource *res, *mem; | ||
| 145 | void __iomem *rng_base = NULL; | ||
| 146 | |||
| 147 | if (rng_dev) | ||
| 148 | return -EBUSY; | ||
| 149 | |||
| 150 | clk = clk_get(&pdev->dev, "rng"); | ||
| 151 | if (IS_ERR(clk)) { | ||
| 152 | dev_err(&pdev->dev, "Could not get rng_clk!\n"); | ||
| 153 | err = PTR_ERR(clk); | ||
| 154 | goto out; | ||
| 155 | } | ||
| 156 | |||
| 157 | clk_enable(clk); | ||
| 158 | |||
| 159 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 160 | if (!res) { | ||
| 161 | err = -ENOENT; | ||
| 162 | goto err_region; | ||
| 163 | } | ||
| 164 | |||
| 165 | mem = request_mem_region(res->start, resource_size(res), pdev->name); | ||
| 166 | if (mem == NULL) { | ||
| 167 | err = -EBUSY; | ||
| 168 | goto err_region; | ||
| 169 | } | ||
| 170 | |||
| 171 | rng_base = ioremap(res->start, resource_size(res)); | ||
| 172 | if (!rng_base) { | ||
| 173 | err = -ENOMEM; | ||
| 174 | goto err_ioremap; | ||
| 175 | } | ||
| 176 | |||
| 177 | mxc_rnga.priv = (unsigned long)rng_base; | ||
| 178 | |||
| 179 | err = hwrng_register(&mxc_rnga); | ||
| 180 | if (err) { | ||
| 181 | dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err); | ||
| 182 | goto err_register; | ||
| 183 | } | ||
| 184 | |||
| 185 | rng_dev = pdev; | ||
| 186 | |||
| 187 | dev_info(&pdev->dev, "MXC RNGA Registered.\n"); | ||
| 188 | |||
| 189 | return 0; | ||
| 190 | |||
| 191 | err_register: | ||
| 192 | iounmap(rng_base); | ||
| 193 | rng_base = NULL; | ||
| 194 | |||
| 195 | err_ioremap: | ||
| 196 | release_mem_region(res->start, resource_size(res)); | ||
| 197 | |||
| 198 | err_region: | ||
| 199 | clk_disable(clk); | ||
| 200 | clk_put(clk); | ||
| 201 | |||
| 202 | out: | ||
| 203 | return err; | ||
| 204 | } | ||
| 205 | |||
| 206 | static int __exit mxc_rnga_remove(struct platform_device *pdev) | ||
| 207 | { | ||
| 208 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 209 | void __iomem *rng_base = (void __iomem *)mxc_rnga.priv; | ||
| 210 | struct clk *clk = clk_get(&pdev->dev, "rng"); | ||
| 211 | |||
| 212 | hwrng_unregister(&mxc_rnga); | ||
| 213 | |||
| 214 | iounmap(rng_base); | ||
| 215 | |||
| 216 | release_mem_region(res->start, resource_size(res)); | ||
| 217 | |||
| 218 | clk_disable(clk); | ||
| 219 | clk_put(clk); | ||
| 220 | |||
| 221 | return 0; | ||
| 222 | } | ||
| 223 | |||
| 224 | static struct platform_driver mxc_rnga_driver = { | ||
| 225 | .driver = { | ||
| 226 | .name = "mxc_rnga", | ||
| 227 | .owner = THIS_MODULE, | ||
| 228 | }, | ||
| 229 | .remove = __exit_p(mxc_rnga_remove), | ||
| 230 | }; | ||
| 231 | |||
| 232 | static int __init mod_init(void) | ||
| 233 | { | ||
| 234 | return platform_driver_probe(&mxc_rnga_driver, mxc_rnga_probe); | ||
| 235 | } | ||
| 236 | |||
| 237 | static void __exit mod_exit(void) | ||
| 238 | { | ||
| 239 | platform_driver_unregister(&mxc_rnga_driver); | ||
| 240 | } | ||
| 241 | |||
| 242 | module_init(mod_init); | ||
| 243 | module_exit(mod_exit); | ||
| 244 | |||
| 245 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
| 246 | MODULE_DESCRIPTION("H/W RNGA driver for i.MX"); | ||
| 247 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index acc7143d9655..035a6c7e59df 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
| @@ -34,10 +34,24 @@ | |||
| 34 | #include <linux/err.h> | 34 | #include <linux/err.h> |
| 35 | #include <linux/clk.h> | 35 | #include <linux/clk.h> |
| 36 | 36 | ||
| 37 | #include <mach/hardware.h> | ||
| 38 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
| 39 | #include <asm/io.h> | 38 | #include <asm/io.h> |
| 40 | #include <mach/i2c.h> | 39 | #include <plat/i2c.h> |
| 40 | |||
| 41 | /* | ||
| 42 | * I2C register offsets will be shifted 0 or 1 bit left, depending on | ||
| 43 | * different SoCs | ||
| 44 | */ | ||
| 45 | #define REG_SHIFT_0 (0 << 0) | ||
| 46 | #define REG_SHIFT_1 (1 << 0) | ||
| 47 | #define REG_SHIFT(d) ((d) & 0x1) | ||
| 48 | |||
| 49 | static const struct platform_device_id i2c_pxa_id_table[] = { | ||
| 50 | { "pxa2xx-i2c", REG_SHIFT_1 }, | ||
| 51 | { "pxa3xx-pwri2c", REG_SHIFT_0 }, | ||
| 52 | { }, | ||
| 53 | }; | ||
| 54 | MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); | ||
| 41 | 55 | ||
| 42 | /* | 56 | /* |
| 43 | * I2C registers and bit definitions | 57 | * I2C registers and bit definitions |
| @@ -985,6 +999,7 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
| 985 | struct pxa_i2c *i2c; | 999 | struct pxa_i2c *i2c; |
| 986 | struct resource *res; | 1000 | struct resource *res; |
| 987 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; | 1001 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; |
| 1002 | struct platform_device_id *id = platform_get_device_id(dev); | ||
| 988 | int ret; | 1003 | int ret; |
| 989 | int irq; | 1004 | int irq; |
| 990 | 1005 | ||
| @@ -1028,7 +1043,7 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
| 1028 | ret = -EIO; | 1043 | ret = -EIO; |
| 1029 | goto eremap; | 1044 | goto eremap; |
| 1030 | } | 1045 | } |
| 1031 | i2c->reg_shift = (cpu_is_pxa3xx() && (dev->id == 1)) ? 0 : 1; | 1046 | i2c->reg_shift = REG_SHIFT(id->driver_data); |
| 1032 | 1047 | ||
| 1033 | i2c->iobase = res->start; | 1048 | i2c->iobase = res->start; |
| 1034 | i2c->iosize = res_len(res); | 1049 | i2c->iosize = res_len(res); |
| @@ -1150,6 +1165,7 @@ static struct platform_driver i2c_pxa_driver = { | |||
| 1150 | .name = "pxa2xx-i2c", | 1165 | .name = "pxa2xx-i2c", |
| 1151 | .owner = THIS_MODULE, | 1166 | .owner = THIS_MODULE, |
| 1152 | }, | 1167 | }, |
| 1168 | .id_table = i2c_pxa_id_table, | ||
| 1153 | }; | 1169 | }; |
| 1154 | 1170 | ||
| 1155 | static int __init i2c_adap_pxa_init(void) | 1171 | static int __init i2c_adap_pxa_init(void) |
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index a28c06d686e1..89b394183a75 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c | |||
| @@ -135,7 +135,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) | |||
| 135 | io->dev.parent = &dev->dev; | 135 | io->dev.parent = &dev->dev; |
| 136 | 136 | ||
| 137 | kmi->io = io; | 137 | kmi->io = io; |
| 138 | kmi->base = ioremap(dev->res.start, KMI_SIZE); | 138 | kmi->base = ioremap(dev->res.start, resource_size(&dev->res)); |
| 139 | if (!kmi->base) { | 139 | if (!kmi->base) { |
| 140 | ret = -ENOMEM; | 140 | ret = -ENOMEM; |
| 141 | goto out; | 141 | goto out; |
diff --git a/drivers/leds/leds-h1940.c b/drivers/leds/leds-h1940.c index 1aa46a390a0d..173d104d9ff2 100644 --- a/drivers/leds/leds-h1940.c +++ b/drivers/leds/leds-h1940.c | |||
| @@ -16,6 +16,8 @@ | |||
| 16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
| 17 | #include <linux/ctype.h> | 17 | #include <linux/ctype.h> |
| 18 | #include <linux/leds.h> | 18 | #include <linux/leds.h> |
| 19 | #include <linux/gpio.h> | ||
| 20 | |||
| 19 | #include <mach/regs-gpio.h> | 21 | #include <mach/regs-gpio.h> |
| 20 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
| 21 | #include <mach/h1940-latch.h> | 23 | #include <mach/h1940-latch.h> |
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c index aa2e7ae0cdae..aa7acf3b9224 100644 --- a/drivers/leds/leds-s3c24xx.c +++ b/drivers/leds/leds-s3c24xx.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/leds.h> | 17 | #include <linux/leds.h> |
| 18 | #include <linux/gpio.h> | ||
| 18 | 19 | ||
| 19 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
| 20 | #include <mach/regs-gpio.h> | 21 | #include <mach/regs-gpio.h> |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 9d48da2fb013..57835f5715fc 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
| @@ -758,10 +758,14 @@ config VIDEO_MX1 | |||
| 758 | ---help--- | 758 | ---help--- |
| 759 | This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface | 759 | This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface |
| 760 | 760 | ||
| 761 | config MX3_VIDEO | ||
| 762 | bool | ||
| 763 | |||
| 761 | config VIDEO_MX3 | 764 | config VIDEO_MX3 |
| 762 | tristate "i.MX3x Camera Sensor Interface driver" | 765 | tristate "i.MX3x Camera Sensor Interface driver" |
| 763 | depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA | 766 | depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA |
| 764 | select VIDEOBUF_DMA_CONTIG | 767 | select VIDEOBUF_DMA_CONTIG |
| 768 | select MX3_VIDEO | ||
| 765 | ---help--- | 769 | ---help--- |
| 766 | This is a v4l2 driver for the i.MX3x Camera Sensor Interface | 770 | This is a v4l2 driver for the i.MX3x Camera Sensor Interface |
| 767 | 771 | ||
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index b4cf691f3f64..3eb87bda14f3 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -155,7 +155,7 @@ config MMC_ATMELMCI_DMA | |||
| 155 | 155 | ||
| 156 | config MMC_IMX | 156 | config MMC_IMX |
| 157 | tristate "Motorola i.MX Multimedia Card Interface support" | 157 | tristate "Motorola i.MX Multimedia Card Interface support" |
| 158 | depends on ARCH_IMX | 158 | depends on ARCH_MX1 |
| 159 | help | 159 | help |
| 160 | This selects the Motorola i.MX Multimedia card Interface. | 160 | This selects the Motorola i.MX Multimedia card Interface. |
| 161 | If you have a i.MX platform with a Multimedia Card slot, | 161 | If you have a i.MX platform with a Multimedia Card slot, |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 7d4febdab286..e1aa8471ab1c 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
| @@ -546,7 +546,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 546 | host->mclk = clk_get_rate(host->clk); | 546 | host->mclk = clk_get_rate(host->clk); |
| 547 | DBG(host, "eventual mclk rate: %u Hz\n", host->mclk); | 547 | DBG(host, "eventual mclk rate: %u Hz\n", host->mclk); |
| 548 | } | 548 | } |
| 549 | host->base = ioremap(dev->res.start, SZ_4K); | 549 | host->base = ioremap(dev->res.start, resource_size(&dev->res)); |
| 550 | if (!host->base) { | 550 | if (!host->base) { |
| 551 | ret = -ENOMEM; | 551 | ret = -ENOMEM; |
| 552 | goto clk_disable; | 552 | goto clk_disable; |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index c40cb96255a2..1cf9cfb3b64f 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
| @@ -1073,7 +1073,6 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
| 1073 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 1073 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
| 1074 | mmc->max_seg_size = mmc->max_req_size; | 1074 | mmc->max_seg_size = mmc->max_req_size; |
| 1075 | 1075 | ||
| 1076 | mmc->ocr_avail = mmc_slot(host).ocr_mask; | ||
| 1077 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; | 1076 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; |
| 1078 | 1077 | ||
| 1079 | if (pdata->slots[host->slot_id].wires >= 8) | 1078 | if (pdata->slots[host->slot_id].wires >= 8) |
| @@ -1110,13 +1109,14 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
| 1110 | goto err_irq; | 1109 | goto err_irq; |
| 1111 | } | 1110 | } |
| 1112 | 1111 | ||
| 1112 | /* initialize power supplies, gpios, etc */ | ||
| 1113 | if (pdata->init != NULL) { | 1113 | if (pdata->init != NULL) { |
| 1114 | if (pdata->init(&pdev->dev) != 0) { | 1114 | if (pdata->init(&pdev->dev) != 0) { |
| 1115 | dev_dbg(mmc_dev(host->mmc), | 1115 | dev_dbg(mmc_dev(host->mmc), "late init error\n"); |
| 1116 | "Unable to configure MMC IRQs\n"); | ||
| 1117 | goto err_irq_cd_init; | 1116 | goto err_irq_cd_init; |
| 1118 | } | 1117 | } |
| 1119 | } | 1118 | } |
| 1119 | mmc->ocr_avail = mmc_slot(host).ocr_mask; | ||
| 1120 | 1120 | ||
| 1121 | /* Request IRQ for card detect */ | 1121 | /* Request IRQ for card detect */ |
| 1122 | if ((mmc_slot(host).card_detect_irq)) { | 1122 | if ((mmc_slot(host).card_detect_irq)) { |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 2db166b7096f..4eb4f37544ab 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/mmc/host.h> | 17 | #include <linux/mmc/host.h> |
| 18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| 19 | #include <linux/cpufreq.h> | 19 | #include <linux/cpufreq.h> |
| 20 | #include <linux/gpio.h> | ||
| 20 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
| 21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
| 22 | 23 | ||
| @@ -789,7 +790,7 @@ static void s3cmci_dma_setup(struct s3cmci_host *host, | |||
| 789 | 790 | ||
| 790 | last_source = source; | 791 | last_source = source; |
| 791 | 792 | ||
| 792 | s3c2410_dma_devconfig(host->dma, source, 3, | 793 | s3c2410_dma_devconfig(host->dma, source, |
| 793 | host->mem->start + host->sdidata); | 794 | host->mem->start + host->sdidata); |
| 794 | 795 | ||
| 795 | if (!setup_ok) { | 796 | if (!setup_ok) { |
| @@ -1121,7 +1122,7 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 1121 | case MMC_POWER_OFF: | 1122 | case MMC_POWER_OFF: |
| 1122 | default: | 1123 | default: |
| 1123 | s3c2410_gpio_setpin(S3C2410_GPE5, 0); | 1124 | s3c2410_gpio_setpin(S3C2410_GPE5, 0); |
| 1124 | s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP); | 1125 | s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPIO_OUTPUT); |
| 1125 | 1126 | ||
| 1126 | if (host->is2440) | 1127 | if (host->is2440) |
| 1127 | mci_con |= S3C2440_SDICON_SDRESET; | 1128 | mci_con |= S3C2440_SDICON_SDRESET; |
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index f2e9de1414df..6391e3dc8002 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c | |||
| @@ -39,7 +39,6 @@ | |||
| 39 | #include <mach/gpmc.h> | 39 | #include <mach/gpmc.h> |
| 40 | #include <mach/onenand.h> | 40 | #include <mach/onenand.h> |
| 41 | #include <mach/gpio.h> | 41 | #include <mach/gpio.h> |
| 42 | #include <mach/pm.h> | ||
| 43 | 42 | ||
| 44 | #include <mach/dma.h> | 43 | #include <mach/dma.h> |
| 45 | 44 | ||
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index a740053d3af3..b6d188115caf 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c | |||
| @@ -456,7 +456,8 @@ static inline void queue_put_desc(unsigned int queue, u32 phys, | |||
| 456 | debug_desc(phys, desc); | 456 | debug_desc(phys, desc); |
| 457 | BUG_ON(phys & 0x1F); | 457 | BUG_ON(phys & 0x1F); |
| 458 | qmgr_put_entry(queue, phys); | 458 | qmgr_put_entry(queue, phys); |
| 459 | BUG_ON(qmgr_stat_overflow(queue)); | 459 | /* Don't check for queue overflow here, we've allocated sufficient |
| 460 | length and queues >= 32 don't support this check anyway. */ | ||
| 460 | } | 461 | } |
| 461 | 462 | ||
| 462 | 463 | ||
| @@ -512,8 +513,8 @@ static int eth_poll(struct napi_struct *napi, int budget) | |||
| 512 | #endif | 513 | #endif |
| 513 | napi_complete(napi); | 514 | napi_complete(napi); |
| 514 | qmgr_enable_irq(rxq); | 515 | qmgr_enable_irq(rxq); |
| 515 | if (!qmgr_stat_empty(rxq) && | 516 | if (!qmgr_stat_below_low_watermark(rxq) && |
| 516 | napi_reschedule(napi)) { | 517 | napi_reschedule(napi)) { /* not empty again */ |
| 517 | #if DEBUG_RX | 518 | #if DEBUG_RX |
| 518 | printk(KERN_DEBUG "%s: eth_poll" | 519 | printk(KERN_DEBUG "%s: eth_poll" |
| 519 | " napi_reschedule successed\n", | 520 | " napi_reschedule successed\n", |
| @@ -630,9 +631,9 @@ static void eth_txdone_irq(void *unused) | |||
| 630 | port->tx_buff_tab[n_desc] = NULL; | 631 | port->tx_buff_tab[n_desc] = NULL; |
| 631 | } | 632 | } |
| 632 | 633 | ||
| 633 | start = qmgr_stat_empty(port->plat->txreadyq); | 634 | start = qmgr_stat_below_low_watermark(port->plat->txreadyq); |
| 634 | queue_put_desc(port->plat->txreadyq, phys, desc); | 635 | queue_put_desc(port->plat->txreadyq, phys, desc); |
| 635 | if (start) { | 636 | if (start) { /* TX-ready queue was empty */ |
| 636 | #if DEBUG_TX | 637 | #if DEBUG_TX |
| 637 | printk(KERN_DEBUG "%s: eth_txdone_irq xmit ready\n", | 638 | printk(KERN_DEBUG "%s: eth_txdone_irq xmit ready\n", |
| 638 | port->netdev->name); | 639 | port->netdev->name); |
| @@ -708,13 +709,14 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 708 | queue_put_desc(TX_QUEUE(port->id), tx_desc_phys(port, n), desc); | 709 | queue_put_desc(TX_QUEUE(port->id), tx_desc_phys(port, n), desc); |
| 709 | dev->trans_start = jiffies; | 710 | dev->trans_start = jiffies; |
| 710 | 711 | ||
| 711 | if (qmgr_stat_empty(txreadyq)) { | 712 | if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */ |
| 712 | #if DEBUG_TX | 713 | #if DEBUG_TX |
| 713 | printk(KERN_DEBUG "%s: eth_xmit queue full\n", dev->name); | 714 | printk(KERN_DEBUG "%s: eth_xmit queue full\n", dev->name); |
| 714 | #endif | 715 | #endif |
| 715 | netif_stop_queue(dev); | 716 | netif_stop_queue(dev); |
| 716 | /* we could miss TX ready interrupt */ | 717 | /* we could miss TX ready interrupt */ |
| 717 | if (!qmgr_stat_empty(txreadyq)) { | 718 | /* really empty in fact */ |
| 719 | if (!qmgr_stat_below_low_watermark(txreadyq)) { | ||
| 718 | #if DEBUG_TX | 720 | #if DEBUG_TX |
| 719 | printk(KERN_DEBUG "%s: eth_xmit ready again\n", | 721 | printk(KERN_DEBUG "%s: eth_xmit ready again\n", |
| 720 | dev->name); | 722 | dev->name); |
| @@ -814,29 +816,29 @@ static int request_queues(struct port *port) | |||
| 814 | int err; | 816 | int err; |
| 815 | 817 | ||
| 816 | err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0, | 818 | err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0, |
| 817 | "%s:RX-free", port->netdev->name); | 819 | "%s:RX-free", port->netdev->name); |
| 818 | if (err) | 820 | if (err) |
| 819 | return err; | 821 | return err; |
| 820 | 822 | ||
| 821 | err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0, | 823 | err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0, |
| 822 | "%s:RX", port->netdev->name); | 824 | "%s:RX", port->netdev->name); |
| 823 | if (err) | 825 | if (err) |
| 824 | goto rel_rxfree; | 826 | goto rel_rxfree; |
| 825 | 827 | ||
| 826 | err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0, | 828 | err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0, |
| 827 | "%s:TX", port->netdev->name); | 829 | "%s:TX", port->netdev->name); |
| 828 | if (err) | 830 | if (err) |
| 829 | goto rel_rx; | 831 | goto rel_rx; |
| 830 | 832 | ||
| 831 | err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0, | 833 | err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0, |
| 832 | "%s:TX-ready", port->netdev->name); | 834 | "%s:TX-ready", port->netdev->name); |
| 833 | if (err) | 835 | if (err) |
| 834 | goto rel_tx; | 836 | goto rel_tx; |
| 835 | 837 | ||
| 836 | /* TX-done queue handles skbs sent out by the NPEs */ | 838 | /* TX-done queue handles skbs sent out by the NPEs */ |
| 837 | if (!ports_open) { | 839 | if (!ports_open) { |
| 838 | err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0, | 840 | err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0, |
| 839 | "%s:TX-done", DRV_NAME); | 841 | "%s:TX-done", DRV_NAME); |
| 840 | if (err) | 842 | if (err) |
| 841 | goto rel_txready; | 843 | goto rel_txready; |
| 842 | } | 844 | } |
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 329f890e2903..f1f773b17fe1 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h | |||
| @@ -45,7 +45,8 @@ | |||
| 45 | defined(CONFIG_MACH_ZYLONITE) ||\ | 45 | defined(CONFIG_MACH_ZYLONITE) ||\ |
| 46 | defined(CONFIG_MACH_LITTLETON) ||\ | 46 | defined(CONFIG_MACH_LITTLETON) ||\ |
| 47 | defined(CONFIG_MACH_ZYLONITE2) ||\ | 47 | defined(CONFIG_MACH_ZYLONITE2) ||\ |
| 48 | defined(CONFIG_ARCH_VIPER) | 48 | defined(CONFIG_ARCH_VIPER) ||\ |
| 49 | defined(CONFIG_MACH_STARGATE2) | ||
| 49 | 50 | ||
| 50 | #include <asm/mach-types.h> | 51 | #include <asm/mach-types.h> |
| 51 | 52 | ||
| @@ -73,7 +74,7 @@ | |||
| 73 | /* We actually can't write halfwords properly if not word aligned */ | 74 | /* We actually can't write halfwords properly if not word aligned */ |
| 74 | static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg) | 75 | static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg) |
| 75 | { | 76 | { |
| 76 | if (machine_is_mainstone() && reg & 2) { | 77 | if ((machine_is_mainstone() || machine_is_stargate2()) && reg & 2) { |
| 77 | unsigned int v = val << 16; | 78 | unsigned int v = val << 16; |
| 78 | v |= readl(ioaddr + (reg & ~2)) & 0xffff; | 79 | v |= readl(ioaddr + (reg & ~2)) & 0xffff; |
| 79 | writel(v, ioaddr + (reg & ~2)); | 80 | writel(v, ioaddr + (reg & ~2)); |
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 765a7f5d6aa4..a6dc317083d3 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c | |||
| @@ -579,7 +579,8 @@ static inline void queue_put_desc(unsigned int queue, u32 phys, | |||
| 579 | debug_desc(phys, desc); | 579 | debug_desc(phys, desc); |
| 580 | BUG_ON(phys & 0x1F); | 580 | BUG_ON(phys & 0x1F); |
| 581 | qmgr_put_entry(queue, phys); | 581 | qmgr_put_entry(queue, phys); |
| 582 | BUG_ON(qmgr_stat_overflow(queue)); | 582 | /* Don't check for queue overflow here, we've allocated sufficient |
| 583 | length and queues >= 32 don't support this check anyway. */ | ||
| 583 | } | 584 | } |
| 584 | 585 | ||
| 585 | 586 | ||
| @@ -789,10 +790,10 @@ static void hss_hdlc_txdone_irq(void *pdev) | |||
| 789 | free_buffer_irq(port->tx_buff_tab[n_desc]); | 790 | free_buffer_irq(port->tx_buff_tab[n_desc]); |
| 790 | port->tx_buff_tab[n_desc] = NULL; | 791 | port->tx_buff_tab[n_desc] = NULL; |
| 791 | 792 | ||
| 792 | start = qmgr_stat_empty(port->plat->txreadyq); | 793 | start = qmgr_stat_below_low_watermark(port->plat->txreadyq); |
| 793 | queue_put_desc(port->plat->txreadyq, | 794 | queue_put_desc(port->plat->txreadyq, |
| 794 | tx_desc_phys(port, n_desc), desc); | 795 | tx_desc_phys(port, n_desc), desc); |
| 795 | if (start) { | 796 | if (start) { /* TX-ready queue was empty */ |
| 796 | #if DEBUG_TX | 797 | #if DEBUG_TX |
| 797 | printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit" | 798 | printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit" |
| 798 | " ready\n", dev->name); | 799 | " ready\n", dev->name); |
| @@ -867,13 +868,13 @@ static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 867 | queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc); | 868 | queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc); |
| 868 | dev->trans_start = jiffies; | 869 | dev->trans_start = jiffies; |
| 869 | 870 | ||
| 870 | if (qmgr_stat_empty(txreadyq)) { | 871 | if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */ |
| 871 | #if DEBUG_TX | 872 | #if DEBUG_TX |
| 872 | printk(KERN_DEBUG "%s: hss_hdlc_xmit queue full\n", dev->name); | 873 | printk(KERN_DEBUG "%s: hss_hdlc_xmit queue full\n", dev->name); |
| 873 | #endif | 874 | #endif |
| 874 | netif_stop_queue(dev); | 875 | netif_stop_queue(dev); |
| 875 | /* we could miss TX ready interrupt */ | 876 | /* we could miss TX ready interrupt */ |
| 876 | if (!qmgr_stat_empty(txreadyq)) { | 877 | if (!qmgr_stat_below_low_watermark(txreadyq)) { |
| 877 | #if DEBUG_TX | 878 | #if DEBUG_TX |
| 878 | printk(KERN_DEBUG "%s: hss_hdlc_xmit ready again\n", | 879 | printk(KERN_DEBUG "%s: hss_hdlc_xmit ready again\n", |
| 879 | dev->name); | 880 | dev->name); |
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 276473543982..fbf965b31c14 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
| @@ -217,7 +217,7 @@ config PCMCIA_PXA2XX | |||
| 217 | depends on ARM && ARCH_PXA && PCMCIA | 217 | depends on ARM && ARCH_PXA && PCMCIA |
| 218 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ | 218 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ |
| 219 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ | 219 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ |
| 220 | || ARCH_VIPER || ARCH_PXA_ESERIES) | 220 | || ARCH_VIPER || ARCH_PXA_ESERIES || MACH_STARGATE2) |
| 221 | help | 221 | help |
| 222 | Say Y here to include support for the PXA2xx PCMCIA controller | 222 | Say Y here to include support for the PXA2xx PCMCIA controller |
| 223 | 223 | ||
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index bbac46327227..047394d98ac2 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
| @@ -73,5 +73,6 @@ pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps4.o | |||
| 73 | pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o | 73 | pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o |
| 74 | pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o | 74 | pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o |
| 75 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o | 75 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o |
| 76 | pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o | ||
| 76 | 77 | ||
| 77 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o $(pxa2xx-obj-y) | 78 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o $(pxa2xx-obj-y) |
diff --git a/drivers/pcmcia/pxa2xx_stargate2.c b/drivers/pcmcia/pxa2xx_stargate2.c new file mode 100644 index 000000000000..490749ea677f --- /dev/null +++ b/drivers/pcmcia/pxa2xx_stargate2.c | |||
| @@ -0,0 +1,174 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/pcmcia/pxa2xx_stargate2.c | ||
| 3 | * | ||
| 4 | * Stargate 2 PCMCIA specific routines. | ||
| 5 | * | ||
| 6 | * Created: December 6, 2005 | ||
| 7 | * Author: Ed C. Epp | ||
| 8 | * Copyright: Intel Corp 2005 | ||
| 9 | * Jonathan Cameron <jic23@cam.ac.uk> 2009 | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/gpio.h> | ||
| 23 | |||
| 24 | #include <pcmcia/ss.h> | ||
| 25 | |||
| 26 | #include <asm/irq.h> | ||
| 27 | #include <asm/mach-types.h> | ||
| 28 | |||
| 29 | #include "soc_common.h" | ||
| 30 | |||
| 31 | #define SG2_S0_BUFF_CTL 120 | ||
| 32 | #define SG2_S0_POWER_CTL 108 | ||
| 33 | #define SG2_S0_GPIO_RESET 82 | ||
| 34 | #define SG2_S0_GPIO_DETECT 53 | ||
| 35 | #define SG2_S0_GPIO_READY 81 | ||
| 36 | |||
| 37 | static struct pcmcia_irqs irqs[] = { | ||
| 38 | { 0, IRQ_GPIO(SG2_S0_GPIO_DETECT), "PCMCIA0 CD" }, | ||
| 39 | }; | ||
| 40 | |||
| 41 | static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | ||
| 42 | { | ||
| 43 | skt->irq = IRQ_GPIO(SG2_S0_GPIO_READY); | ||
| 44 | return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
| 45 | } | ||
| 46 | |||
| 47 | static void sg2_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | ||
| 48 | { | ||
| 49 | soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
| 50 | } | ||
| 51 | |||
| 52 | static void sg2_pcmcia_socket_state(struct soc_pcmcia_socket *skt, | ||
| 53 | struct pcmcia_state *state) | ||
| 54 | { | ||
| 55 | state->detect = !gpio_get_value(SG2_S0_GPIO_DETECT); | ||
| 56 | state->ready = !!gpio_get_value(SG2_S0_GPIO_READY); | ||
| 57 | state->bvd1 = 0; /* not available - battery detect on card */ | ||
| 58 | state->bvd2 = 0; /* not available */ | ||
| 59 | state->vs_3v = 1; /* not available - voltage detect for card */ | ||
| 60 | state->vs_Xv = 0; /* not available */ | ||
| 61 | state->wrprot = 0; /* not available - write protect */ | ||
| 62 | } | ||
| 63 | |||
| 64 | static int sg2_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, | ||
| 65 | const socket_state_t *state) | ||
| 66 | { | ||
| 67 | /* Enable card power */ | ||
| 68 | switch (state->Vcc) { | ||
| 69 | case 0: | ||
| 70 | /* sets power ctl register high */ | ||
| 71 | gpio_set_value(SG2_S0_POWER_CTL, 1); | ||
| 72 | break; | ||
| 73 | case 33: | ||
| 74 | case 50: | ||
| 75 | /* sets power control register low (clear) */ | ||
| 76 | gpio_set_value(SG2_S0_POWER_CTL, 0); | ||
| 77 | msleep(100); | ||
| 78 | break; | ||
| 79 | default: | ||
| 80 | pr_err("%s(): bad Vcc %u\n", | ||
| 81 | __func__, state->Vcc); | ||
| 82 | return -1; | ||
| 83 | } | ||
| 84 | |||
| 85 | /* reset */ | ||
| 86 | gpio_set_value(SG2_S0_GPIO_RESET, !!(state->flags & SS_RESET)); | ||
| 87 | |||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | static void sg2_pcmcia_socket_init(struct soc_pcmcia_socket *skt) | ||
| 92 | { | ||
| 93 | soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
| 94 | } | ||
| 95 | |||
| 96 | static void sg2_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | ||
| 97 | { | ||
| 98 | soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
| 99 | } | ||
| 100 | |||
| 101 | static struct pcmcia_low_level sg2_pcmcia_ops __initdata = { | ||
| 102 | .owner = THIS_MODULE, | ||
| 103 | .hw_init = sg2_pcmcia_hw_init, | ||
| 104 | .hw_shutdown = sg2_pcmcia_hw_shutdown, | ||
| 105 | .socket_state = sg2_pcmcia_socket_state, | ||
| 106 | .configure_socket = sg2_pcmcia_configure_socket, | ||
| 107 | .socket_init = sg2_pcmcia_socket_init, | ||
| 108 | .socket_suspend = sg2_pcmcia_socket_suspend, | ||
| 109 | .nr = 1, | ||
| 110 | }; | ||
| 111 | |||
| 112 | static struct platform_device *sg2_pcmcia_device; | ||
| 113 | |||
| 114 | static int __init sg2_pcmcia_init(void) | ||
| 115 | { | ||
| 116 | int ret; | ||
| 117 | |||
| 118 | if (!machine_is_stargate2()) | ||
| 119 | return -ENODEV; | ||
| 120 | |||
| 121 | sg2_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); | ||
| 122 | if (!sg2_pcmcia_device) | ||
| 123 | return -ENOMEM; | ||
| 124 | |||
| 125 | ret = gpio_request(SG2_S0_BUFF_CTL, "SG2 CF buff ctl"); | ||
| 126 | if (ret) | ||
| 127 | goto error_put_platform_device; | ||
| 128 | ret = gpio_request(SG2_S0_POWER_CTL, "SG2 CF power ctl"); | ||
| 129 | if (ret) | ||
| 130 | goto error_free_gpio_buff_ctl; | ||
| 131 | ret = gpio_request(SG2_S0_GPIO_RESET, "SG2 CF reset"); | ||
| 132 | if (ret) | ||
| 133 | goto error_free_gpio_power_ctl; | ||
| 134 | /* Set gpio directions */ | ||
| 135 | gpio_direction_output(SG2_S0_BUFF_CTL, 0); | ||
| 136 | gpio_direction_output(SG2_S0_POWER_CTL, 1); | ||
| 137 | gpio_direction_output(SG2_S0_GPIO_RESET, 1); | ||
| 138 | |||
| 139 | ret = platform_device_add_data(sg2_pcmcia_device, | ||
| 140 | &sg2_pcmcia_ops, | ||
| 141 | sizeof(sg2_pcmcia_ops)); | ||
| 142 | if (ret) | ||
| 143 | goto error_free_gpio_reset; | ||
| 144 | |||
| 145 | ret = platform_device_add(sg2_pcmcia_device); | ||
| 146 | if (ret) | ||
| 147 | goto error_free_gpio_reset; | ||
| 148 | |||
| 149 | return 0; | ||
| 150 | error_free_gpio_reset: | ||
| 151 | gpio_free(SG2_S0_GPIO_RESET); | ||
| 152 | error_free_gpio_power_ctl: | ||
| 153 | gpio_free(SG2_S0_POWER_CTL); | ||
| 154 | error_free_gpio_buff_ctl: | ||
| 155 | gpio_free(SG2_S0_BUFF_CTL); | ||
| 156 | error_put_platform_device: | ||
| 157 | platform_device_put(sg2_pcmcia_device); | ||
| 158 | |||
| 159 | return ret; | ||
| 160 | } | ||
| 161 | |||
| 162 | static void __exit sg2_pcmcia_exit(void) | ||
| 163 | { | ||
| 164 | platform_device_unregister(sg2_pcmcia_device); | ||
| 165 | gpio_free(SG2_S0_BUFF_CTL); | ||
| 166 | gpio_free(SG2_S0_POWER_CTL); | ||
| 167 | gpio_free(SG2_S0_GPIO_RESET); | ||
| 168 | } | ||
| 169 | |||
| 170 | fs_initcall(sg2_pcmcia_init); | ||
| 171 | module_exit(sg2_pcmcia_exit); | ||
| 172 | |||
| 173 | MODULE_LICENSE("GPL"); | ||
| 174 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); | ||
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index f7a3283dd029..551332e4ed02 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c | |||
| @@ -12,32 +12,56 @@ | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <mach/hardware.h> | 15 | #include <linux/io.h> |
| 16 | |||
| 17 | #define EP93XX_RTC_DATA 0x000 | ||
| 18 | #define EP93XX_RTC_MATCH 0x004 | ||
| 19 | #define EP93XX_RTC_STATUS 0x008 | ||
| 20 | #define EP93XX_RTC_STATUS_INTR (1<<0) | ||
| 21 | #define EP93XX_RTC_LOAD 0x00C | ||
| 22 | #define EP93XX_RTC_CONTROL 0x010 | ||
| 23 | #define EP93XX_RTC_CONTROL_MIE (1<<0) | ||
| 24 | #define EP93XX_RTC_SWCOMP 0x108 | ||
| 25 | #define EP93XX_RTC_SWCOMP_DEL_MASK 0x001f0000 | ||
| 26 | #define EP93XX_RTC_SWCOMP_DEL_SHIFT 16 | ||
| 27 | #define EP93XX_RTC_SWCOMP_INT_MASK 0x0000ffff | ||
| 28 | #define EP93XX_RTC_SWCOMP_INT_SHIFT 0 | ||
| 29 | |||
| 30 | #define DRV_VERSION "0.3" | ||
| 16 | 31 | ||
| 17 | #define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x)) | 32 | /* |
| 18 | #define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000) | 33 | * struct device dev.platform_data is used to store our private data |
| 19 | #define EP93XX_RTC_LOAD EP93XX_RTC_REG(0x000C) | 34 | * because struct rtc_device does not have a variable to hold it. |
| 20 | #define EP93XX_RTC_SWCOMP EP93XX_RTC_REG(0x0108) | 35 | */ |
| 21 | 36 | struct ep93xx_rtc { | |
| 22 | #define DRV_VERSION "0.2" | 37 | void __iomem *mmio_base; |
| 38 | }; | ||
| 23 | 39 | ||
| 24 | static int ep93xx_get_swcomp(struct device *dev, unsigned short *preload, | 40 | static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload, |
| 25 | unsigned short *delete) | 41 | unsigned short *delete) |
| 26 | { | 42 | { |
| 27 | unsigned short comp = __raw_readl(EP93XX_RTC_SWCOMP); | 43 | struct ep93xx_rtc *ep93xx_rtc = dev->platform_data; |
| 44 | unsigned long comp; | ||
| 45 | |||
| 46 | comp = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_SWCOMP); | ||
| 28 | 47 | ||
| 29 | if (preload) | 48 | if (preload) |
| 30 | *preload = comp & 0xffff; | 49 | *preload = (comp & EP93XX_RTC_SWCOMP_INT_MASK) |
| 50 | >> EP93XX_RTC_SWCOMP_INT_SHIFT; | ||
| 31 | 51 | ||
| 32 | if (delete) | 52 | if (delete) |
| 33 | *delete = (comp >> 16) & 0x1f; | 53 | *delete = (comp & EP93XX_RTC_SWCOMP_DEL_MASK) |
| 54 | >> EP93XX_RTC_SWCOMP_DEL_SHIFT; | ||
| 34 | 55 | ||
| 35 | return 0; | 56 | return 0; |
| 36 | } | 57 | } |
| 37 | 58 | ||
| 38 | static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm) | 59 | static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 39 | { | 60 | { |
| 40 | unsigned long time = __raw_readl(EP93XX_RTC_DATA); | 61 | struct ep93xx_rtc *ep93xx_rtc = dev->platform_data; |
| 62 | unsigned long time; | ||
| 63 | |||
| 64 | time = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA); | ||
| 41 | 65 | ||
| 42 | rtc_time_to_tm(time, tm); | 66 | rtc_time_to_tm(time, tm); |
| 43 | return 0; | 67 | return 0; |
| @@ -45,7 +69,9 @@ static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 45 | 69 | ||
| 46 | static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs) | 70 | static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs) |
| 47 | { | 71 | { |
| 48 | __raw_writel(secs + 1, EP93XX_RTC_LOAD); | 72 | struct ep93xx_rtc *ep93xx_rtc = dev->platform_data; |
| 73 | |||
| 74 | __raw_writel(secs + 1, ep93xx_rtc->mmio_base + EP93XX_RTC_LOAD); | ||
| 49 | return 0; | 75 | return 0; |
| 50 | } | 76 | } |
| 51 | 77 | ||
| @@ -53,7 +79,7 @@ static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq) | |||
| 53 | { | 79 | { |
| 54 | unsigned short preload, delete; | 80 | unsigned short preload, delete; |
| 55 | 81 | ||
| 56 | ep93xx_get_swcomp(dev, &preload, &delete); | 82 | ep93xx_rtc_get_swcomp(dev, &preload, &delete); |
| 57 | 83 | ||
| 58 | seq_printf(seq, "preload\t\t: %d\n", preload); | 84 | seq_printf(seq, "preload\t\t: %d\n", preload); |
| 59 | seq_printf(seq, "delete\t\t: %d\n", delete); | 85 | seq_printf(seq, "delete\t\t: %d\n", delete); |
| @@ -67,54 +93,104 @@ static const struct rtc_class_ops ep93xx_rtc_ops = { | |||
| 67 | .proc = ep93xx_rtc_proc, | 93 | .proc = ep93xx_rtc_proc, |
| 68 | }; | 94 | }; |
| 69 | 95 | ||
| 70 | static ssize_t ep93xx_sysfs_show_comp_preload(struct device *dev, | 96 | static ssize_t ep93xx_rtc_show_comp_preload(struct device *dev, |
| 71 | struct device_attribute *attr, char *buf) | 97 | struct device_attribute *attr, char *buf) |
| 72 | { | 98 | { |
| 73 | unsigned short preload; | 99 | unsigned short preload; |
| 74 | 100 | ||
| 75 | ep93xx_get_swcomp(dev, &preload, NULL); | 101 | ep93xx_rtc_get_swcomp(dev, &preload, NULL); |
| 76 | 102 | ||
| 77 | return sprintf(buf, "%d\n", preload); | 103 | return sprintf(buf, "%d\n", preload); |
| 78 | } | 104 | } |
| 79 | static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_sysfs_show_comp_preload, NULL); | 105 | static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_rtc_show_comp_preload, NULL); |
| 80 | 106 | ||
| 81 | static ssize_t ep93xx_sysfs_show_comp_delete(struct device *dev, | 107 | static ssize_t ep93xx_rtc_show_comp_delete(struct device *dev, |
| 82 | struct device_attribute *attr, char *buf) | 108 | struct device_attribute *attr, char *buf) |
| 83 | { | 109 | { |
| 84 | unsigned short delete; | 110 | unsigned short delete; |
| 85 | 111 | ||
| 86 | ep93xx_get_swcomp(dev, NULL, &delete); | 112 | ep93xx_rtc_get_swcomp(dev, NULL, &delete); |
| 87 | 113 | ||
| 88 | return sprintf(buf, "%d\n", delete); | 114 | return sprintf(buf, "%d\n", delete); |
| 89 | } | 115 | } |
| 90 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_sysfs_show_comp_delete, NULL); | 116 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL); |
| 91 | 117 | ||
| 92 | 118 | ||
| 93 | static int __devinit ep93xx_rtc_probe(struct platform_device *dev) | 119 | static int __init ep93xx_rtc_probe(struct platform_device *pdev) |
| 94 | { | 120 | { |
| 95 | struct rtc_device *rtc = rtc_device_register("ep93xx", | 121 | struct ep93xx_rtc *ep93xx_rtc; |
| 96 | &dev->dev, &ep93xx_rtc_ops, THIS_MODULE); | 122 | struct resource *res; |
| 123 | struct rtc_device *rtc; | ||
| 124 | int err; | ||
| 125 | |||
| 126 | ep93xx_rtc = kzalloc(sizeof(struct ep93xx_rtc), GFP_KERNEL); | ||
| 127 | if (ep93xx_rtc == NULL) | ||
| 128 | return -ENOMEM; | ||
| 129 | |||
| 130 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 131 | if (res == NULL) | ||
| 132 | return -ENXIO; | ||
| 133 | |||
| 134 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
| 135 | if (res == NULL) | ||
| 136 | return -EBUSY; | ||
| 137 | |||
| 138 | ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res)); | ||
| 139 | if (ep93xx_rtc->mmio_base == NULL) { | ||
| 140 | err = -ENXIO; | ||
| 141 | goto fail; | ||
| 142 | } | ||
| 97 | 143 | ||
| 144 | pdev->dev.platform_data = ep93xx_rtc; | ||
| 145 | |||
| 146 | rtc = rtc_device_register(pdev->name, | ||
| 147 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); | ||
| 98 | if (IS_ERR(rtc)) { | 148 | if (IS_ERR(rtc)) { |
| 99 | return PTR_ERR(rtc); | 149 | err = PTR_ERR(rtc); |
| 150 | goto fail; | ||
| 100 | } | 151 | } |
| 101 | 152 | ||
| 102 | platform_set_drvdata(dev, rtc); | 153 | platform_set_drvdata(pdev, rtc); |
| 103 | 154 | ||
| 104 | device_create_file(&dev->dev, &dev_attr_comp_preload); | 155 | err = device_create_file(&pdev->dev, &dev_attr_comp_preload); |
| 105 | device_create_file(&dev->dev, &dev_attr_comp_delete); | 156 | if (err) |
| 157 | goto fail; | ||
| 158 | err = device_create_file(&pdev->dev, &dev_attr_comp_delete); | ||
| 159 | if (err) { | ||
| 160 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
| 161 | goto fail; | ||
| 162 | } | ||
| 106 | 163 | ||
| 107 | return 0; | 164 | return 0; |
| 165 | |||
| 166 | fail: | ||
| 167 | if (ep93xx_rtc->mmio_base) { | ||
| 168 | iounmap(ep93xx_rtc->mmio_base); | ||
| 169 | pdev->dev.platform_data = NULL; | ||
| 170 | } | ||
| 171 | release_mem_region(res->start, resource_size(res)); | ||
| 172 | return err; | ||
| 108 | } | 173 | } |
| 109 | 174 | ||
| 110 | static int __devexit ep93xx_rtc_remove(struct platform_device *dev) | 175 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) |
| 111 | { | 176 | { |
| 112 | struct rtc_device *rtc = platform_get_drvdata(dev); | 177 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
| 178 | struct ep93xx_rtc *ep93xx_rtc = pdev->dev.platform_data; | ||
| 179 | struct resource *res; | ||
| 180 | |||
| 181 | /* cleanup sysfs */ | ||
| 182 | device_remove_file(&pdev->dev, &dev_attr_comp_delete); | ||
| 183 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
| 184 | |||
| 185 | rtc_device_unregister(rtc); | ||
| 186 | |||
| 187 | iounmap(ep93xx_rtc->mmio_base); | ||
| 188 | pdev->dev.platform_data = NULL; | ||
| 113 | 189 | ||
| 114 | if (rtc) | 190 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 115 | rtc_device_unregister(rtc); | 191 | release_mem_region(res->start, resource_size(res)); |
| 116 | 192 | ||
| 117 | platform_set_drvdata(dev, NULL); | 193 | platform_set_drvdata(pdev, NULL); |
| 118 | 194 | ||
| 119 | return 0; | 195 | return 0; |
| 120 | } | 196 | } |
| @@ -122,23 +198,22 @@ static int __devexit ep93xx_rtc_remove(struct platform_device *dev) | |||
| 122 | /* work with hotplug and coldplug */ | 198 | /* work with hotplug and coldplug */ |
| 123 | MODULE_ALIAS("platform:ep93xx-rtc"); | 199 | MODULE_ALIAS("platform:ep93xx-rtc"); |
| 124 | 200 | ||
| 125 | static struct platform_driver ep93xx_rtc_platform_driver = { | 201 | static struct platform_driver ep93xx_rtc_driver = { |
| 126 | .driver = { | 202 | .driver = { |
| 127 | .name = "ep93xx-rtc", | 203 | .name = "ep93xx-rtc", |
| 128 | .owner = THIS_MODULE, | 204 | .owner = THIS_MODULE, |
| 129 | }, | 205 | }, |
| 130 | .probe = ep93xx_rtc_probe, | 206 | .remove = __exit_p(ep93xx_rtc_remove), |
| 131 | .remove = __devexit_p(ep93xx_rtc_remove), | ||
| 132 | }; | 207 | }; |
| 133 | 208 | ||
| 134 | static int __init ep93xx_rtc_init(void) | 209 | static int __init ep93xx_rtc_init(void) |
| 135 | { | 210 | { |
| 136 | return platform_driver_register(&ep93xx_rtc_platform_driver); | 211 | return platform_driver_probe(&ep93xx_rtc_driver, ep93xx_rtc_probe); |
| 137 | } | 212 | } |
| 138 | 213 | ||
| 139 | static void __exit ep93xx_rtc_exit(void) | 214 | static void __exit ep93xx_rtc_exit(void) |
| 140 | { | 215 | { |
| 141 | platform_driver_unregister(&ep93xx_rtc_platform_driver); | 216 | platform_driver_unregister(&ep93xx_rtc_driver); |
| 142 | } | 217 | } |
| 143 | 218 | ||
| 144 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | 219 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); |
diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index aaf1f75fa293..457231bb1029 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c | |||
| @@ -117,7 +117,7 @@ static int pl030_probe(struct amba_device *dev, struct amba_id *id) | |||
| 117 | goto err_rtc; | 117 | goto err_rtc; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | rtc->base = ioremap(dev->res.start, SZ_4K); | 120 | rtc->base = ioremap(dev->res.start, resource_size(&dev->res)); |
| 121 | if (!rtc->base) { | 121 | if (!rtc->base) { |
| 122 | ret = -ENOMEM; | 122 | ret = -ENOMEM; |
| 123 | goto err_map; | 123 | goto err_map; |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 451fc13784d1..f41873f98f66 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
| @@ -142,8 +142,7 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id) | |||
| 142 | goto out; | 142 | goto out; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | ldata->base = ioremap(adev->res.start, | 145 | ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); |
| 146 | adev->res.end - adev->res.start + 1); | ||
| 147 | if (!ldata->base) { | 146 | if (!ldata->base) { |
| 148 | ret = -ENOMEM; | 147 | ret = -ENOMEM; |
| 149 | goto out_no_remap; | 148 | goto out_no_remap; |
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index cdc049d4350f..58a4879c7e48 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
| @@ -686,7 +686,7 @@ static int pl010_probe(struct amba_device *dev, struct amba_id *id) | |||
| 686 | goto out; | 686 | goto out; |
| 687 | } | 687 | } |
| 688 | 688 | ||
| 689 | base = ioremap(dev->res.start, PAGE_SIZE); | 689 | base = ioremap(dev->res.start, resource_size(&dev->res)); |
| 690 | if (!base) { | 690 | if (!base) { |
| 691 | ret = -ENOMEM; | 691 | ret = -ENOMEM; |
| 692 | goto free; | 692 | goto free; |
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 88fdac51b6c5..bf82e28770a9 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c | |||
| @@ -70,6 +70,23 @@ struct uart_amba_port { | |||
| 70 | struct clk *clk; | 70 | struct clk *clk; |
| 71 | unsigned int im; /* interrupt mask */ | 71 | unsigned int im; /* interrupt mask */ |
| 72 | unsigned int old_status; | 72 | unsigned int old_status; |
| 73 | unsigned int ifls; /* vendor-specific */ | ||
| 74 | }; | ||
| 75 | |||
| 76 | /* There is by now at least one vendor with differing details, so handle it */ | ||
| 77 | struct vendor_data { | ||
| 78 | unsigned int ifls; | ||
| 79 | unsigned int fifosize; | ||
| 80 | }; | ||
| 81 | |||
| 82 | static struct vendor_data vendor_arm = { | ||
| 83 | .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, | ||
| 84 | .fifosize = 16, | ||
| 85 | }; | ||
| 86 | |||
| 87 | static struct vendor_data vendor_st = { | ||
| 88 | .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, | ||
| 89 | .fifosize = 64, | ||
| 73 | }; | 90 | }; |
| 74 | 91 | ||
| 75 | static void pl011_stop_tx(struct uart_port *port) | 92 | static void pl011_stop_tx(struct uart_port *port) |
| @@ -360,8 +377,7 @@ static int pl011_startup(struct uart_port *port) | |||
| 360 | if (retval) | 377 | if (retval) |
| 361 | goto clk_dis; | 378 | goto clk_dis; |
| 362 | 379 | ||
| 363 | writew(UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, | 380 | writew(uap->ifls, uap->port.membase + UART011_IFLS); |
| 364 | uap->port.membase + UART011_IFLS); | ||
| 365 | 381 | ||
| 366 | /* | 382 | /* |
| 367 | * Provoke TX FIFO interrupt into asserting. | 383 | * Provoke TX FIFO interrupt into asserting. |
| @@ -732,6 +748,7 @@ static struct uart_driver amba_reg = { | |||
| 732 | static int pl011_probe(struct amba_device *dev, struct amba_id *id) | 748 | static int pl011_probe(struct amba_device *dev, struct amba_id *id) |
| 733 | { | 749 | { |
| 734 | struct uart_amba_port *uap; | 750 | struct uart_amba_port *uap; |
| 751 | struct vendor_data *vendor = id->data; | ||
| 735 | void __iomem *base; | 752 | void __iomem *base; |
| 736 | int i, ret; | 753 | int i, ret; |
| 737 | 754 | ||
| @@ -750,7 +767,7 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id) | |||
| 750 | goto out; | 767 | goto out; |
| 751 | } | 768 | } |
| 752 | 769 | ||
| 753 | base = ioremap(dev->res.start, PAGE_SIZE); | 770 | base = ioremap(dev->res.start, resource_size(&dev->res)); |
| 754 | if (!base) { | 771 | if (!base) { |
| 755 | ret = -ENOMEM; | 772 | ret = -ENOMEM; |
| 756 | goto free; | 773 | goto free; |
| @@ -762,12 +779,13 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id) | |||
| 762 | goto unmap; | 779 | goto unmap; |
| 763 | } | 780 | } |
| 764 | 781 | ||
| 782 | uap->ifls = vendor->ifls; | ||
| 765 | uap->port.dev = &dev->dev; | 783 | uap->port.dev = &dev->dev; |
| 766 | uap->port.mapbase = dev->res.start; | 784 | uap->port.mapbase = dev->res.start; |
| 767 | uap->port.membase = base; | 785 | uap->port.membase = base; |
| 768 | uap->port.iotype = UPIO_MEM; | 786 | uap->port.iotype = UPIO_MEM; |
| 769 | uap->port.irq = dev->irq[0]; | 787 | uap->port.irq = dev->irq[0]; |
| 770 | uap->port.fifosize = 16; | 788 | uap->port.fifosize = vendor->fifosize; |
| 771 | uap->port.ops = &amba_pl011_pops; | 789 | uap->port.ops = &amba_pl011_pops; |
| 772 | uap->port.flags = UPF_BOOT_AUTOCONF; | 790 | uap->port.flags = UPF_BOOT_AUTOCONF; |
| 773 | uap->port.line = i; | 791 | uap->port.line = i; |
| @@ -812,6 +830,12 @@ static struct amba_id pl011_ids[] __initdata = { | |||
| 812 | { | 830 | { |
| 813 | .id = 0x00041011, | 831 | .id = 0x00041011, |
| 814 | .mask = 0x000fffff, | 832 | .mask = 0x000fffff, |
| 833 | .data = &vendor_arm, | ||
| 834 | }, | ||
| 835 | { | ||
| 836 | .id = 0x00380802, | ||
| 837 | .mask = 0x00ffffff, | ||
| 838 | .data = &vendor_st, | ||
| 815 | }, | 839 | }, |
| 816 | { 0, 0 }, | 840 | { 0, 0 }, |
| 817 | }; | 841 | }; |
| @@ -845,7 +869,11 @@ static void __exit pl011_exit(void) | |||
| 845 | uart_unregister_driver(&amba_reg); | 869 | uart_unregister_driver(&amba_reg); |
| 846 | } | 870 | } |
| 847 | 871 | ||
| 848 | module_init(pl011_init); | 872 | /* |
| 873 | * While this can be a module, if builtin it's most likely the console | ||
| 874 | * So let's leave module_exit but move module_init to an earlier place | ||
| 875 | */ | ||
| 876 | arch_initcall(pl011_init); | ||
| 849 | module_exit(pl011_exit); | 877 | module_exit(pl011_exit); |
| 850 | 878 | ||
| 851 | MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd"); | 879 | MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd"); |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 7b5d1de9cfe3..285b414f3054 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
| @@ -71,7 +71,7 @@ | |||
| 71 | #define ONEMS 0xb0 /* One Millisecond register */ | 71 | #define ONEMS 0xb0 /* One Millisecond register */ |
| 72 | #define UTS 0xb4 /* UART Test Register */ | 72 | #define UTS 0xb4 /* UART Test Register */ |
| 73 | #endif | 73 | #endif |
| 74 | #if defined(CONFIG_ARCH_IMX) || defined(CONFIG_ARCH_MX1) | 74 | #ifdef CONFIG_ARCH_MX1 |
| 75 | #define BIPR1 0xb0 /* Incremental Preset Register 1 */ | 75 | #define BIPR1 0xb0 /* Incremental Preset Register 1 */ |
| 76 | #define BIPR2 0xb4 /* Incremental Preset Register 2 */ | 76 | #define BIPR2 0xb4 /* Incremental Preset Register 2 */ |
| 77 | #define BIPR3 0xb8 /* Incremental Preset Register 3 */ | 77 | #define BIPR3 0xb8 /* Incremental Preset Register 3 */ |
| @@ -101,7 +101,7 @@ | |||
| 101 | #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ | 101 | #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ |
| 102 | #define UCR1_SNDBRK (1<<4) /* Send break */ | 102 | #define UCR1_SNDBRK (1<<4) /* Send break */ |
| 103 | #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ | 103 | #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ |
| 104 | #if defined(CONFIG_ARCH_IMX) || defined(CONFIG_ARCH_MX1) | 104 | #ifdef CONFIG_ARCH_MX1 |
| 105 | #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ | 105 | #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ |
| 106 | #endif | 106 | #endif |
| 107 | #if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2 | 107 | #if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2 |
| @@ -132,7 +132,7 @@ | |||
| 132 | #define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ | 132 | #define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ |
| 133 | #define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ | 133 | #define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ |
| 134 | #define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ | 134 | #define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ |
| 135 | #ifdef CONFIG_ARCH_IMX | 135 | #ifdef CONFIG_ARCH_MX1 |
| 136 | #define UCR3_REF25 (1<<3) /* Ref freq 25 MHz, only on mx1 */ | 136 | #define UCR3_REF25 (1<<3) /* Ref freq 25 MHz, only on mx1 */ |
| 137 | #define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz, only on mx1 */ | 137 | #define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz, only on mx1 */ |
| 138 | #endif | 138 | #endif |
| @@ -186,13 +186,6 @@ | |||
| 186 | #define UTS_SOFTRST (1<<0) /* Software reset */ | 186 | #define UTS_SOFTRST (1<<0) /* Software reset */ |
| 187 | 187 | ||
| 188 | /* We've been assigned a range on the "Low-density serial ports" major */ | 188 | /* We've been assigned a range on the "Low-density serial ports" major */ |
| 189 | #ifdef CONFIG_ARCH_IMX | ||
| 190 | #define SERIAL_IMX_MAJOR 204 | ||
| 191 | #define MINOR_START 41 | ||
| 192 | #define DEV_NAME "ttySMX" | ||
| 193 | #define MAX_INTERNAL_IRQ IMX_IRQS | ||
| 194 | #endif | ||
| 195 | |||
| 196 | #ifdef CONFIG_ARCH_MXC | 189 | #ifdef CONFIG_ARCH_MXC |
| 197 | #define SERIAL_IMX_MAJOR 207 | 190 | #define SERIAL_IMX_MAJOR 207 |
| 198 | #define MINOR_START 16 | 191 | #define MINOR_START 16 |
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 957494775413..e8aae227b5e0 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
| @@ -118,7 +118,7 @@ config SPI_GPIO | |||
| 118 | 118 | ||
| 119 | config SPI_IMX | 119 | config SPI_IMX |
| 120 | tristate "Freescale iMX SPI controller" | 120 | tristate "Freescale iMX SPI controller" |
| 121 | depends on ARCH_IMX && EXPERIMENTAL | 121 | depends on ARCH_MX1 && EXPERIMENTAL |
| 122 | help | 122 | help |
| 123 | This enables using the Freescale iMX SPI controller in master | 123 | This enables using the Freescale iMX SPI controller in master |
| 124 | mode. | 124 | mode. |
| @@ -171,6 +171,15 @@ config SPI_ORION | |||
| 171 | help | 171 | help |
| 172 | This enables using the SPI master controller on the Orion chips. | 172 | This enables using the SPI master controller on the Orion chips. |
| 173 | 173 | ||
| 174 | config SPI_PL022 | ||
| 175 | tristate "ARM AMBA PL022 SSP controller (EXPERIMENTAL)" | ||
| 176 | depends on ARM_AMBA && EXPERIMENTAL | ||
| 177 | default y if MACH_U300 | ||
| 178 | help | ||
| 179 | This selects the ARM(R) AMBA(R) PrimeCell PL022 SSP | ||
| 180 | controller. If you have an embedded system with an AMBA(R) | ||
| 181 | bus and a PL022 controller, say Y or M here. | ||
| 182 | |||
| 174 | config SPI_PXA2XX | 183 | config SPI_PXA2XX |
| 175 | tristate "PXA2xx SSP SPI master" | 184 | tristate "PXA2xx SSP SPI master" |
| 176 | depends on ARCH_PXA && EXPERIMENTAL | 185 | depends on ARCH_PXA && EXPERIMENTAL |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 5d0451936d86..ecfadb180482 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
| @@ -23,6 +23,7 @@ obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o | |||
| 23 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o | 23 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o |
| 24 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o | 24 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o |
| 25 | obj-$(CONFIG_SPI_ORION) += orion_spi.o | 25 | obj-$(CONFIG_SPI_ORION) += orion_spi.o |
| 26 | obj-$(CONFIG_SPI_PL022) += amba-pl022.o | ||
| 26 | obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o | 27 | obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o |
| 27 | obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o | 28 | obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o |
| 28 | obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o | 29 | obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o |
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c new file mode 100644 index 000000000000..da76797ce8b9 --- /dev/null +++ b/drivers/spi/amba-pl022.c | |||
| @@ -0,0 +1,1866 @@ | |||
| 1 | /* | ||
| 2 | * drivers/spi/amba-pl022.c | ||
| 3 | * | ||
| 4 | * A driver for the ARM PL022 PrimeCell SSP/SPI bus master. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2008-2009 ST-Ericsson AB | ||
| 7 | * Copyright (C) 2006 STMicroelectronics Pvt. Ltd. | ||
| 8 | * | ||
| 9 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
| 10 | * | ||
| 11 | * Initial version inspired by: | ||
| 12 | * linux-2.6.17-rc3-mm1/drivers/spi/pxa2xx_spi.c | ||
| 13 | * Initial adoption to PL022 by: | ||
| 14 | * Sachin Verma <sachin.verma@st.com> | ||
| 15 | * | ||
| 16 | * This program is free software; you can redistribute it and/or modify | ||
| 17 | * it under the terms of the GNU General Public License as published by | ||
| 18 | * the Free Software Foundation; either version 2 of the License, or | ||
| 19 | * (at your option) any later version. | ||
| 20 | * | ||
| 21 | * This program is distributed in the hope that it will be useful, | ||
| 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 24 | * GNU General Public License for more details. | ||
| 25 | */ | ||
| 26 | |||
| 27 | /* | ||
| 28 | * TODO: | ||
| 29 | * - add timeout on polled transfers | ||
| 30 | * - add generic DMA framework support | ||
| 31 | */ | ||
| 32 | |||
| 33 | #include <linux/init.h> | ||
| 34 | #include <linux/module.h> | ||
| 35 | #include <linux/device.h> | ||
| 36 | #include <linux/ioport.h> | ||
| 37 | #include <linux/errno.h> | ||
| 38 | #include <linux/interrupt.h> | ||
| 39 | #include <linux/spi/spi.h> | ||
| 40 | #include <linux/workqueue.h> | ||
| 41 | #include <linux/errno.h> | ||
| 42 | #include <linux/delay.h> | ||
| 43 | #include <linux/clk.h> | ||
| 44 | #include <linux/err.h> | ||
| 45 | #include <linux/amba/bus.h> | ||
| 46 | #include <linux/amba/pl022.h> | ||
| 47 | #include <linux/io.h> | ||
| 48 | #include <linux/delay.h> | ||
| 49 | |||
| 50 | /* | ||
| 51 | * This macro is used to define some register default values. | ||
| 52 | * reg is masked with mask, the OR:ed with an (again masked) | ||
| 53 | * val shifted sb steps to the left. | ||
| 54 | */ | ||
| 55 | #define SSP_WRITE_BITS(reg, val, mask, sb) \ | ||
| 56 | ((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask)))) | ||
| 57 | |||
| 58 | /* | ||
| 59 | * This macro is also used to define some default values. | ||
| 60 | * It will just shift val by sb steps to the left and mask | ||
| 61 | * the result with mask. | ||
| 62 | */ | ||
| 63 | #define GEN_MASK_BITS(val, mask, sb) \ | ||
| 64 | (((val)<<(sb)) & (mask)) | ||
| 65 | |||
| 66 | #define DRIVE_TX 0 | ||
| 67 | #define DO_NOT_DRIVE_TX 1 | ||
| 68 | |||
| 69 | #define DO_NOT_QUEUE_DMA 0 | ||
| 70 | #define QUEUE_DMA 1 | ||
| 71 | |||
| 72 | #define RX_TRANSFER 1 | ||
| 73 | #define TX_TRANSFER 2 | ||
| 74 | |||
| 75 | /* | ||
| 76 | * Macros to access SSP Registers with their offsets | ||
| 77 | */ | ||
| 78 | #define SSP_CR0(r) (r + 0x000) | ||
| 79 | #define SSP_CR1(r) (r + 0x004) | ||
| 80 | #define SSP_DR(r) (r + 0x008) | ||
| 81 | #define SSP_SR(r) (r + 0x00C) | ||
| 82 | #define SSP_CPSR(r) (r + 0x010) | ||
| 83 | #define SSP_IMSC(r) (r + 0x014) | ||
| 84 | #define SSP_RIS(r) (r + 0x018) | ||
| 85 | #define SSP_MIS(r) (r + 0x01C) | ||
| 86 | #define SSP_ICR(r) (r + 0x020) | ||
| 87 | #define SSP_DMACR(r) (r + 0x024) | ||
| 88 | #define SSP_ITCR(r) (r + 0x080) | ||
| 89 | #define SSP_ITIP(r) (r + 0x084) | ||
| 90 | #define SSP_ITOP(r) (r + 0x088) | ||
| 91 | #define SSP_TDR(r) (r + 0x08C) | ||
| 92 | |||
| 93 | #define SSP_PID0(r) (r + 0xFE0) | ||
| 94 | #define SSP_PID1(r) (r + 0xFE4) | ||
| 95 | #define SSP_PID2(r) (r + 0xFE8) | ||
| 96 | #define SSP_PID3(r) (r + 0xFEC) | ||
| 97 | |||
| 98 | #define SSP_CID0(r) (r + 0xFF0) | ||
| 99 | #define SSP_CID1(r) (r + 0xFF4) | ||
| 100 | #define SSP_CID2(r) (r + 0xFF8) | ||
| 101 | #define SSP_CID3(r) (r + 0xFFC) | ||
| 102 | |||
| 103 | /* | ||
| 104 | * SSP Control Register 0 - SSP_CR0 | ||
| 105 | */ | ||
| 106 | #define SSP_CR0_MASK_DSS (0x1FUL << 0) | ||
| 107 | #define SSP_CR0_MASK_HALFDUP (0x1UL << 5) | ||
| 108 | #define SSP_CR0_MASK_SPO (0x1UL << 6) | ||
| 109 | #define SSP_CR0_MASK_SPH (0x1UL << 7) | ||
| 110 | #define SSP_CR0_MASK_SCR (0xFFUL << 8) | ||
| 111 | #define SSP_CR0_MASK_CSS (0x1FUL << 16) | ||
| 112 | #define SSP_CR0_MASK_FRF (0x3UL << 21) | ||
| 113 | |||
| 114 | /* | ||
| 115 | * SSP Control Register 0 - SSP_CR1 | ||
| 116 | */ | ||
| 117 | #define SSP_CR1_MASK_LBM (0x1UL << 0) | ||
| 118 | #define SSP_CR1_MASK_SSE (0x1UL << 1) | ||
| 119 | #define SSP_CR1_MASK_MS (0x1UL << 2) | ||
| 120 | #define SSP_CR1_MASK_SOD (0x1UL << 3) | ||
| 121 | #define SSP_CR1_MASK_RENDN (0x1UL << 4) | ||
| 122 | #define SSP_CR1_MASK_TENDN (0x1UL << 5) | ||
| 123 | #define SSP_CR1_MASK_MWAIT (0x1UL << 6) | ||
| 124 | #define SSP_CR1_MASK_RXIFLSEL (0x7UL << 7) | ||
| 125 | #define SSP_CR1_MASK_TXIFLSEL (0x7UL << 10) | ||
| 126 | |||
| 127 | /* | ||
| 128 | * SSP Data Register - SSP_DR | ||
| 129 | */ | ||
| 130 | #define SSP_DR_MASK_DATA 0xFFFFFFFF | ||
| 131 | |||
| 132 | /* | ||
| 133 | * SSP Status Register - SSP_SR | ||
| 134 | */ | ||
| 135 | #define SSP_SR_MASK_TFE (0x1UL << 0) /* Transmit FIFO empty */ | ||
| 136 | #define SSP_SR_MASK_TNF (0x1UL << 1) /* Transmit FIFO not full */ | ||
| 137 | #define SSP_SR_MASK_RNE (0x1UL << 2) /* Receive FIFO not empty */ | ||
| 138 | #define SSP_SR_MASK_RFF (0x1UL << 3) /* Receive FIFO full */ | ||
| 139 | #define SSP_SR_MASK_BSY (0x1UL << 4) /* Busy Flag */ | ||
| 140 | |||
| 141 | /* | ||
| 142 | * SSP Clock Prescale Register - SSP_CPSR | ||
| 143 | */ | ||
| 144 | #define SSP_CPSR_MASK_CPSDVSR (0xFFUL << 0) | ||
| 145 | |||
| 146 | /* | ||
| 147 | * SSP Interrupt Mask Set/Clear Register - SSP_IMSC | ||
| 148 | */ | ||
| 149 | #define SSP_IMSC_MASK_RORIM (0x1UL << 0) /* Receive Overrun Interrupt mask */ | ||
| 150 | #define SSP_IMSC_MASK_RTIM (0x1UL << 1) /* Receive timeout Interrupt mask */ | ||
| 151 | #define SSP_IMSC_MASK_RXIM (0x1UL << 2) /* Receive FIFO Interrupt mask */ | ||
| 152 | #define SSP_IMSC_MASK_TXIM (0x1UL << 3) /* Transmit FIFO Interrupt mask */ | ||
| 153 | |||
| 154 | /* | ||
| 155 | * SSP Raw Interrupt Status Register - SSP_RIS | ||
| 156 | */ | ||
| 157 | /* Receive Overrun Raw Interrupt status */ | ||
| 158 | #define SSP_RIS_MASK_RORRIS (0x1UL << 0) | ||
| 159 | /* Receive Timeout Raw Interrupt status */ | ||
| 160 | #define SSP_RIS_MASK_RTRIS (0x1UL << 1) | ||
| 161 | /* Receive FIFO Raw Interrupt status */ | ||
| 162 | #define SSP_RIS_MASK_RXRIS (0x1UL << 2) | ||
| 163 | /* Transmit FIFO Raw Interrupt status */ | ||
| 164 | #define SSP_RIS_MASK_TXRIS (0x1UL << 3) | ||
| 165 | |||
| 166 | /* | ||
| 167 | * SSP Masked Interrupt Status Register - SSP_MIS | ||
| 168 | */ | ||
| 169 | /* Receive Overrun Masked Interrupt status */ | ||
| 170 | #define SSP_MIS_MASK_RORMIS (0x1UL << 0) | ||
| 171 | /* Receive Timeout Masked Interrupt status */ | ||
| 172 | #define SSP_MIS_MASK_RTMIS (0x1UL << 1) | ||
| 173 | /* Receive FIFO Masked Interrupt status */ | ||
| 174 | #define SSP_MIS_MASK_RXMIS (0x1UL << 2) | ||
| 175 | /* Transmit FIFO Masked Interrupt status */ | ||
| 176 | #define SSP_MIS_MASK_TXMIS (0x1UL << 3) | ||
| 177 | |||
| 178 | /* | ||
| 179 | * SSP Interrupt Clear Register - SSP_ICR | ||
| 180 | */ | ||
| 181 | /* Receive Overrun Raw Clear Interrupt bit */ | ||
| 182 | #define SSP_ICR_MASK_RORIC (0x1UL << 0) | ||
| 183 | /* Receive Timeout Clear Interrupt bit */ | ||
| 184 | #define SSP_ICR_MASK_RTIC (0x1UL << 1) | ||
| 185 | |||
| 186 | /* | ||
| 187 | * SSP DMA Control Register - SSP_DMACR | ||
| 188 | */ | ||
| 189 | /* Receive DMA Enable bit */ | ||
| 190 | #define SSP_DMACR_MASK_RXDMAE (0x1UL << 0) | ||
| 191 | /* Transmit DMA Enable bit */ | ||
| 192 | #define SSP_DMACR_MASK_TXDMAE (0x1UL << 1) | ||
| 193 | |||
| 194 | /* | ||
| 195 | * SSP Integration Test control Register - SSP_ITCR | ||
| 196 | */ | ||
| 197 | #define SSP_ITCR_MASK_ITEN (0x1UL << 0) | ||
| 198 | #define SSP_ITCR_MASK_TESTFIFO (0x1UL << 1) | ||
| 199 | |||
| 200 | /* | ||
| 201 | * SSP Integration Test Input Register - SSP_ITIP | ||
| 202 | */ | ||
| 203 | #define ITIP_MASK_SSPRXD (0x1UL << 0) | ||
| 204 | #define ITIP_MASK_SSPFSSIN (0x1UL << 1) | ||
| 205 | #define ITIP_MASK_SSPCLKIN (0x1UL << 2) | ||
| 206 | #define ITIP_MASK_RXDMAC (0x1UL << 3) | ||
| 207 | #define ITIP_MASK_TXDMAC (0x1UL << 4) | ||
| 208 | #define ITIP_MASK_SSPTXDIN (0x1UL << 5) | ||
| 209 | |||
| 210 | /* | ||
| 211 | * SSP Integration Test output Register - SSP_ITOP | ||
| 212 | */ | ||
| 213 | #define ITOP_MASK_SSPTXD (0x1UL << 0) | ||
| 214 | #define ITOP_MASK_SSPFSSOUT (0x1UL << 1) | ||
| 215 | #define ITOP_MASK_SSPCLKOUT (0x1UL << 2) | ||
| 216 | #define ITOP_MASK_SSPOEn (0x1UL << 3) | ||
| 217 | #define ITOP_MASK_SSPCTLOEn (0x1UL << 4) | ||
| 218 | #define ITOP_MASK_RORINTR (0x1UL << 5) | ||
| 219 | #define ITOP_MASK_RTINTR (0x1UL << 6) | ||
| 220 | #define ITOP_MASK_RXINTR (0x1UL << 7) | ||
| 221 | #define ITOP_MASK_TXINTR (0x1UL << 8) | ||
| 222 | #define ITOP_MASK_INTR (0x1UL << 9) | ||
| 223 | #define ITOP_MASK_RXDMABREQ (0x1UL << 10) | ||
| 224 | #define ITOP_MASK_RXDMASREQ (0x1UL << 11) | ||
| 225 | #define ITOP_MASK_TXDMABREQ (0x1UL << 12) | ||
| 226 | #define ITOP_MASK_TXDMASREQ (0x1UL << 13) | ||
| 227 | |||
| 228 | /* | ||
| 229 | * SSP Test Data Register - SSP_TDR | ||
| 230 | */ | ||
| 231 | #define TDR_MASK_TESTDATA (0xFFFFFFFF) | ||
| 232 | |||
| 233 | /* | ||
| 234 | * Message State | ||
| 235 | * we use the spi_message.state (void *) pointer to | ||
| 236 | * hold a single state value, that's why all this | ||
| 237 | * (void *) casting is done here. | ||
| 238 | */ | ||
| 239 | #define STATE_START ((void *) 0) | ||
| 240 | #define STATE_RUNNING ((void *) 1) | ||
| 241 | #define STATE_DONE ((void *) 2) | ||
| 242 | #define STATE_ERROR ((void *) -1) | ||
| 243 | |||
| 244 | /* | ||
| 245 | * Queue State | ||
| 246 | */ | ||
| 247 | #define QUEUE_RUNNING (0) | ||
| 248 | #define QUEUE_STOPPED (1) | ||
| 249 | /* | ||
| 250 | * SSP State - Whether Enabled or Disabled | ||
| 251 | */ | ||
| 252 | #define SSP_DISABLED (0) | ||
| 253 | #define SSP_ENABLED (1) | ||
| 254 | |||
| 255 | /* | ||
| 256 | * SSP DMA State - Whether DMA Enabled or Disabled | ||
| 257 | */ | ||
| 258 | #define SSP_DMA_DISABLED (0) | ||
| 259 | #define SSP_DMA_ENABLED (1) | ||
| 260 | |||
| 261 | /* | ||
| 262 | * SSP Clock Defaults | ||
| 263 | */ | ||
| 264 | #define NMDK_SSP_DEFAULT_CLKRATE 0x2 | ||
| 265 | #define NMDK_SSP_DEFAULT_PRESCALE 0x40 | ||
| 266 | |||
| 267 | /* | ||
| 268 | * SSP Clock Parameter ranges | ||
| 269 | */ | ||
| 270 | #define CPSDVR_MIN 0x02 | ||
| 271 | #define CPSDVR_MAX 0xFE | ||
| 272 | #define SCR_MIN 0x00 | ||
| 273 | #define SCR_MAX 0xFF | ||
| 274 | |||
| 275 | /* | ||
| 276 | * SSP Interrupt related Macros | ||
| 277 | */ | ||
| 278 | #define DEFAULT_SSP_REG_IMSC 0x0UL | ||
| 279 | #define DISABLE_ALL_INTERRUPTS DEFAULT_SSP_REG_IMSC | ||
| 280 | #define ENABLE_ALL_INTERRUPTS (~DEFAULT_SSP_REG_IMSC) | ||
| 281 | |||
| 282 | #define CLEAR_ALL_INTERRUPTS 0x3 | ||
| 283 | |||
| 284 | |||
| 285 | /* | ||
| 286 | * The type of reading going on on this chip | ||
| 287 | */ | ||
| 288 | enum ssp_reading { | ||
| 289 | READING_NULL, | ||
| 290 | READING_U8, | ||
| 291 | READING_U16, | ||
| 292 | READING_U32 | ||
| 293 | }; | ||
| 294 | |||
| 295 | /** | ||
| 296 | * The type of writing going on on this chip | ||
| 297 | */ | ||
| 298 | enum ssp_writing { | ||
| 299 | WRITING_NULL, | ||
| 300 | WRITING_U8, | ||
| 301 | WRITING_U16, | ||
| 302 | WRITING_U32 | ||
| 303 | }; | ||
| 304 | |||
| 305 | /** | ||
| 306 | * struct vendor_data - vendor-specific config parameters | ||
| 307 | * for PL022 derivates | ||
| 308 | * @fifodepth: depth of FIFOs (both) | ||
| 309 | * @max_bpw: maximum number of bits per word | ||
| 310 | * @unidir: supports unidirection transfers | ||
| 311 | */ | ||
| 312 | struct vendor_data { | ||
| 313 | int fifodepth; | ||
| 314 | int max_bpw; | ||
| 315 | bool unidir; | ||
| 316 | }; | ||
| 317 | |||
| 318 | /** | ||
| 319 | * struct pl022 - This is the private SSP driver data structure | ||
| 320 | * @adev: AMBA device model hookup | ||
| 321 | * @phybase: The physical memory where the SSP device resides | ||
| 322 | * @virtbase: The virtual memory where the SSP is mapped | ||
| 323 | * @master: SPI framework hookup | ||
| 324 | * @master_info: controller-specific data from machine setup | ||
| 325 | * @regs: SSP controller register's virtual address | ||
| 326 | * @pump_messages: Work struct for scheduling work to the workqueue | ||
| 327 | * @lock: spinlock to syncronise access to driver data | ||
| 328 | * @workqueue: a workqueue on which any spi_message request is queued | ||
| 329 | * @busy: workqueue is busy | ||
| 330 | * @run: workqueue is running | ||
| 331 | * @pump_transfers: Tasklet used in Interrupt Transfer mode | ||
| 332 | * @cur_msg: Pointer to current spi_message being processed | ||
| 333 | * @cur_transfer: Pointer to current spi_transfer | ||
| 334 | * @cur_chip: pointer to current clients chip(assigned from controller_state) | ||
| 335 | * @tx: current position in TX buffer to be read | ||
| 336 | * @tx_end: end position in TX buffer to be read | ||
| 337 | * @rx: current position in RX buffer to be written | ||
| 338 | * @rx_end: end position in RX buffer to be written | ||
| 339 | * @readingtype: the type of read currently going on | ||
| 340 | * @writingtype: the type or write currently going on | ||
| 341 | */ | ||
| 342 | struct pl022 { | ||
| 343 | struct amba_device *adev; | ||
| 344 | struct vendor_data *vendor; | ||
| 345 | resource_size_t phybase; | ||
| 346 | void __iomem *virtbase; | ||
| 347 | struct clk *clk; | ||
| 348 | struct spi_master *master; | ||
| 349 | struct pl022_ssp_controller *master_info; | ||
| 350 | /* Driver message queue */ | ||
| 351 | struct workqueue_struct *workqueue; | ||
| 352 | struct work_struct pump_messages; | ||
| 353 | spinlock_t queue_lock; | ||
| 354 | struct list_head queue; | ||
| 355 | int busy; | ||
| 356 | int run; | ||
| 357 | /* Message transfer pump */ | ||
| 358 | struct tasklet_struct pump_transfers; | ||
| 359 | struct spi_message *cur_msg; | ||
| 360 | struct spi_transfer *cur_transfer; | ||
| 361 | struct chip_data *cur_chip; | ||
| 362 | void *tx; | ||
| 363 | void *tx_end; | ||
| 364 | void *rx; | ||
| 365 | void *rx_end; | ||
| 366 | enum ssp_reading read; | ||
| 367 | enum ssp_writing write; | ||
| 368 | }; | ||
| 369 | |||
| 370 | /** | ||
| 371 | * struct chip_data - To maintain runtime state of SSP for each client chip | ||
| 372 | * @cr0: Value of control register CR0 of SSP | ||
| 373 | * @cr1: Value of control register CR1 of SSP | ||
| 374 | * @dmacr: Value of DMA control Register of SSP | ||
| 375 | * @cpsr: Value of Clock prescale register | ||
| 376 | * @n_bytes: how many bytes(power of 2) reqd for a given data width of client | ||
| 377 | * @enable_dma: Whether to enable DMA or not | ||
| 378 | * @write: function ptr to be used to write when doing xfer for this chip | ||
| 379 | * @read: function ptr to be used to read when doing xfer for this chip | ||
| 380 | * @cs_control: chip select callback provided by chip | ||
| 381 | * @xfer_type: polling/interrupt/DMA | ||
| 382 | * | ||
| 383 | * Runtime state of the SSP controller, maintained per chip, | ||
| 384 | * This would be set according to the current message that would be served | ||
| 385 | */ | ||
| 386 | struct chip_data { | ||
| 387 | u16 cr0; | ||
| 388 | u16 cr1; | ||
| 389 | u16 dmacr; | ||
| 390 | u16 cpsr; | ||
| 391 | u8 n_bytes; | ||
| 392 | u8 enable_dma:1; | ||
| 393 | enum ssp_reading read; | ||
| 394 | enum ssp_writing write; | ||
| 395 | void (*cs_control) (u32 command); | ||
| 396 | int xfer_type; | ||
| 397 | }; | ||
| 398 | |||
| 399 | /** | ||
| 400 | * null_cs_control - Dummy chip select function | ||
| 401 | * @command: select/delect the chip | ||
| 402 | * | ||
| 403 | * If no chip select function is provided by client this is used as dummy | ||
| 404 | * chip select | ||
| 405 | */ | ||
| 406 | static void null_cs_control(u32 command) | ||
| 407 | { | ||
| 408 | pr_debug("pl022: dummy chip select control, CS=0x%x\n", command); | ||
| 409 | } | ||
| 410 | |||
| 411 | /** | ||
| 412 | * giveback - current spi_message is over, schedule next message and call | ||
| 413 | * callback of this message. Assumes that caller already | ||
| 414 | * set message->status; dma and pio irqs are blocked | ||
| 415 | * @pl022: SSP driver private data structure | ||
| 416 | */ | ||
| 417 | static void giveback(struct pl022 *pl022) | ||
| 418 | { | ||
| 419 | struct spi_transfer *last_transfer; | ||
| 420 | unsigned long flags; | ||
| 421 | struct spi_message *msg; | ||
| 422 | void (*curr_cs_control) (u32 command); | ||
| 423 | |||
| 424 | /* | ||
| 425 | * This local reference to the chip select function | ||
| 426 | * is needed because we set curr_chip to NULL | ||
| 427 | * as a step toward termininating the message. | ||
| 428 | */ | ||
| 429 | curr_cs_control = pl022->cur_chip->cs_control; | ||
| 430 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
| 431 | msg = pl022->cur_msg; | ||
| 432 | pl022->cur_msg = NULL; | ||
| 433 | pl022->cur_transfer = NULL; | ||
| 434 | pl022->cur_chip = NULL; | ||
| 435 | queue_work(pl022->workqueue, &pl022->pump_messages); | ||
| 436 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 437 | |||
| 438 | last_transfer = list_entry(msg->transfers.prev, | ||
| 439 | struct spi_transfer, | ||
| 440 | transfer_list); | ||
| 441 | |||
| 442 | /* Delay if requested before any change in chip select */ | ||
| 443 | if (last_transfer->delay_usecs) | ||
| 444 | /* | ||
| 445 | * FIXME: This runs in interrupt context. | ||
| 446 | * Is this really smart? | ||
| 447 | */ | ||
| 448 | udelay(last_transfer->delay_usecs); | ||
| 449 | |||
| 450 | /* | ||
| 451 | * Drop chip select UNLESS cs_change is true or we are returning | ||
| 452 | * a message with an error, or next message is for another chip | ||
| 453 | */ | ||
| 454 | if (!last_transfer->cs_change) | ||
| 455 | curr_cs_control(SSP_CHIP_DESELECT); | ||
| 456 | else { | ||
| 457 | struct spi_message *next_msg; | ||
| 458 | |||
| 459 | /* Holding of cs was hinted, but we need to make sure | ||
| 460 | * the next message is for the same chip. Don't waste | ||
| 461 | * time with the following tests unless this was hinted. | ||
| 462 | * | ||
| 463 | * We cannot postpone this until pump_messages, because | ||
| 464 | * after calling msg->complete (below) the driver that | ||
| 465 | * sent the current message could be unloaded, which | ||
| 466 | * could invalidate the cs_control() callback... | ||
| 467 | */ | ||
| 468 | |||
| 469 | /* get a pointer to the next message, if any */ | ||
| 470 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
| 471 | if (list_empty(&pl022->queue)) | ||
| 472 | next_msg = NULL; | ||
| 473 | else | ||
| 474 | next_msg = list_entry(pl022->queue.next, | ||
| 475 | struct spi_message, queue); | ||
| 476 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 477 | |||
| 478 | /* see if the next and current messages point | ||
| 479 | * to the same chip | ||
| 480 | */ | ||
| 481 | if (next_msg && next_msg->spi != msg->spi) | ||
| 482 | next_msg = NULL; | ||
| 483 | if (!next_msg || msg->state == STATE_ERROR) | ||
| 484 | curr_cs_control(SSP_CHIP_DESELECT); | ||
| 485 | } | ||
| 486 | msg->state = NULL; | ||
| 487 | if (msg->complete) | ||
| 488 | msg->complete(msg->context); | ||
| 489 | /* This message is completed, so let's turn off the clock! */ | ||
| 490 | clk_disable(pl022->clk); | ||
| 491 | } | ||
| 492 | |||
| 493 | /** | ||
| 494 | * flush - flush the FIFO to reach a clean state | ||
| 495 | * @pl022: SSP driver private data structure | ||
| 496 | */ | ||
| 497 | static int flush(struct pl022 *pl022) | ||
| 498 | { | ||
| 499 | unsigned long limit = loops_per_jiffy << 1; | ||
| 500 | |||
| 501 | dev_dbg(&pl022->adev->dev, "flush\n"); | ||
| 502 | do { | ||
| 503 | while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) | ||
| 504 | readw(SSP_DR(pl022->virtbase)); | ||
| 505 | } while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--); | ||
| 506 | return limit; | ||
| 507 | } | ||
| 508 | |||
| 509 | /** | ||
| 510 | * restore_state - Load configuration of current chip | ||
| 511 | * @pl022: SSP driver private data structure | ||
| 512 | */ | ||
| 513 | static void restore_state(struct pl022 *pl022) | ||
| 514 | { | ||
| 515 | struct chip_data *chip = pl022->cur_chip; | ||
| 516 | |||
| 517 | writew(chip->cr0, SSP_CR0(pl022->virtbase)); | ||
| 518 | writew(chip->cr1, SSP_CR1(pl022->virtbase)); | ||
| 519 | writew(chip->dmacr, SSP_DMACR(pl022->virtbase)); | ||
| 520 | writew(chip->cpsr, SSP_CPSR(pl022->virtbase)); | ||
| 521 | writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | ||
| 522 | writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); | ||
| 523 | } | ||
| 524 | |||
| 525 | /** | ||
| 526 | * load_ssp_default_config - Load default configuration for SSP | ||
| 527 | * @pl022: SSP driver private data structure | ||
| 528 | */ | ||
| 529 | |||
| 530 | /* | ||
| 531 | * Default SSP Register Values | ||
| 532 | */ | ||
| 533 | #define DEFAULT_SSP_REG_CR0 ( \ | ||
| 534 | GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS, 0) | \ | ||
| 535 | GEN_MASK_BITS(SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, SSP_CR0_MASK_HALFDUP, 5) | \ | ||
| 536 | GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \ | ||
| 537 | GEN_MASK_BITS(SSP_CLK_FALLING_EDGE, SSP_CR0_MASK_SPH, 7) | \ | ||
| 538 | GEN_MASK_BITS(NMDK_SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) | \ | ||
| 539 | GEN_MASK_BITS(SSP_BITS_8, SSP_CR0_MASK_CSS, 16) | \ | ||
| 540 | GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF, 21) \ | ||
| 541 | ) | ||
| 542 | |||
| 543 | #define DEFAULT_SSP_REG_CR1 ( \ | ||
| 544 | GEN_MASK_BITS(LOOPBACK_DISABLED, SSP_CR1_MASK_LBM, 0) | \ | ||
| 545 | GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \ | ||
| 546 | GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \ | ||
| 547 | GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) | \ | ||
| 548 | GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN, 4) | \ | ||
| 549 | GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN, 5) | \ | ||
| 550 | GEN_MASK_BITS(SSP_MWIRE_WAIT_ZERO, SSP_CR1_MASK_MWAIT, 6) |\ | ||
| 551 | GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL, 7) | \ | ||
| 552 | GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL, 10) \ | ||
| 553 | ) | ||
| 554 | |||
| 555 | #define DEFAULT_SSP_REG_CPSR ( \ | ||
| 556 | GEN_MASK_BITS(NMDK_SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \ | ||
| 557 | ) | ||
| 558 | |||
| 559 | #define DEFAULT_SSP_REG_DMACR (\ | ||
| 560 | GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_RXDMAE, 0) | \ | ||
| 561 | GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_TXDMAE, 1) \ | ||
| 562 | ) | ||
| 563 | |||
| 564 | |||
| 565 | static void load_ssp_default_config(struct pl022 *pl022) | ||
| 566 | { | ||
| 567 | writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase)); | ||
| 568 | writew(DEFAULT_SSP_REG_CR1, SSP_CR1(pl022->virtbase)); | ||
| 569 | writew(DEFAULT_SSP_REG_DMACR, SSP_DMACR(pl022->virtbase)); | ||
| 570 | writew(DEFAULT_SSP_REG_CPSR, SSP_CPSR(pl022->virtbase)); | ||
| 571 | writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | ||
| 572 | writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); | ||
| 573 | } | ||
| 574 | |||
| 575 | /** | ||
| 576 | * This will write to TX and read from RX according to the parameters | ||
| 577 | * set in pl022. | ||
| 578 | */ | ||
| 579 | static void readwriter(struct pl022 *pl022) | ||
| 580 | { | ||
| 581 | |||
| 582 | /* | ||
| 583 | * The FIFO depth is different inbetween primecell variants. | ||
| 584 | * I believe filling in too much in the FIFO might cause | ||
| 585 | * errons in 8bit wide transfers on ARM variants (just 8 words | ||
| 586 | * FIFO, means only 8x8 = 64 bits in FIFO) at least. | ||
| 587 | * | ||
| 588 | * FIXME: currently we have no logic to account for this. | ||
| 589 | * perhaps there is even something broken in HW regarding | ||
| 590 | * 8bit transfers (it doesn't fail on 16bit) so this needs | ||
| 591 | * more investigation... | ||
| 592 | */ | ||
| 593 | dev_dbg(&pl022->adev->dev, | ||
| 594 | "%s, rx: %p, rxend: %p, tx: %p, txend: %p\n", | ||
| 595 | __func__, pl022->rx, pl022->rx_end, pl022->tx, pl022->tx_end); | ||
| 596 | |||
| 597 | /* Read as much as you can */ | ||
| 598 | while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) | ||
| 599 | && (pl022->rx < pl022->rx_end)) { | ||
| 600 | switch (pl022->read) { | ||
| 601 | case READING_NULL: | ||
| 602 | readw(SSP_DR(pl022->virtbase)); | ||
| 603 | break; | ||
| 604 | case READING_U8: | ||
| 605 | *(u8 *) (pl022->rx) = | ||
| 606 | readw(SSP_DR(pl022->virtbase)) & 0xFFU; | ||
| 607 | break; | ||
| 608 | case READING_U16: | ||
| 609 | *(u16 *) (pl022->rx) = | ||
| 610 | (u16) readw(SSP_DR(pl022->virtbase)); | ||
| 611 | break; | ||
| 612 | case READING_U32: | ||
| 613 | *(u32 *) (pl022->rx) = | ||
| 614 | readl(SSP_DR(pl022->virtbase)); | ||
| 615 | break; | ||
| 616 | } | ||
| 617 | pl022->rx += (pl022->cur_chip->n_bytes); | ||
| 618 | } | ||
| 619 | /* | ||
| 620 | * Write as much as you can, while keeping an eye on the RX FIFO! | ||
| 621 | */ | ||
| 622 | while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF) | ||
| 623 | && (pl022->tx < pl022->tx_end)) { | ||
| 624 | switch (pl022->write) { | ||
| 625 | case WRITING_NULL: | ||
| 626 | writew(0x0, SSP_DR(pl022->virtbase)); | ||
| 627 | break; | ||
| 628 | case WRITING_U8: | ||
| 629 | writew(*(u8 *) (pl022->tx), SSP_DR(pl022->virtbase)); | ||
| 630 | break; | ||
| 631 | case WRITING_U16: | ||
| 632 | writew((*(u16 *) (pl022->tx)), SSP_DR(pl022->virtbase)); | ||
| 633 | break; | ||
| 634 | case WRITING_U32: | ||
| 635 | writel(*(u32 *) (pl022->tx), SSP_DR(pl022->virtbase)); | ||
| 636 | break; | ||
| 637 | } | ||
| 638 | pl022->tx += (pl022->cur_chip->n_bytes); | ||
| 639 | /* | ||
| 640 | * This inner reader takes care of things appearing in the RX | ||
| 641 | * FIFO as we're transmitting. This will happen a lot since the | ||
| 642 | * clock starts running when you put things into the TX FIFO, | ||
| 643 | * and then things are continously clocked into the RX FIFO. | ||
| 644 | */ | ||
| 645 | while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) | ||
| 646 | && (pl022->rx < pl022->rx_end)) { | ||
| 647 | switch (pl022->read) { | ||
| 648 | case READING_NULL: | ||
| 649 | readw(SSP_DR(pl022->virtbase)); | ||
| 650 | break; | ||
| 651 | case READING_U8: | ||
| 652 | *(u8 *) (pl022->rx) = | ||
| 653 | readw(SSP_DR(pl022->virtbase)) & 0xFFU; | ||
| 654 | break; | ||
| 655 | case READING_U16: | ||
| 656 | *(u16 *) (pl022->rx) = | ||
| 657 | (u16) readw(SSP_DR(pl022->virtbase)); | ||
| 658 | break; | ||
| 659 | case READING_U32: | ||
| 660 | *(u32 *) (pl022->rx) = | ||
| 661 | readl(SSP_DR(pl022->virtbase)); | ||
| 662 | break; | ||
| 663 | } | ||
| 664 | pl022->rx += (pl022->cur_chip->n_bytes); | ||
| 665 | } | ||
| 666 | } | ||
| 667 | /* | ||
| 668 | * When we exit here the TX FIFO should be full and the RX FIFO | ||
| 669 | * should be empty | ||
| 670 | */ | ||
| 671 | } | ||
| 672 | |||
| 673 | |||
| 674 | /** | ||
| 675 | * next_transfer - Move to the Next transfer in the current spi message | ||
| 676 | * @pl022: SSP driver private data structure | ||
| 677 | * | ||
| 678 | * This function moves though the linked list of spi transfers in the | ||
| 679 | * current spi message and returns with the state of current spi | ||
| 680 | * message i.e whether its last transfer is done(STATE_DONE) or | ||
| 681 | * Next transfer is ready(STATE_RUNNING) | ||
| 682 | */ | ||
| 683 | static void *next_transfer(struct pl022 *pl022) | ||
| 684 | { | ||
| 685 | struct spi_message *msg = pl022->cur_msg; | ||
| 686 | struct spi_transfer *trans = pl022->cur_transfer; | ||
| 687 | |||
| 688 | /* Move to next transfer */ | ||
| 689 | if (trans->transfer_list.next != &msg->transfers) { | ||
| 690 | pl022->cur_transfer = | ||
| 691 | list_entry(trans->transfer_list.next, | ||
| 692 | struct spi_transfer, transfer_list); | ||
| 693 | return STATE_RUNNING; | ||
| 694 | } | ||
| 695 | return STATE_DONE; | ||
| 696 | } | ||
| 697 | /** | ||
| 698 | * pl022_interrupt_handler - Interrupt handler for SSP controller | ||
| 699 | * | ||
| 700 | * This function handles interrupts generated for an interrupt based transfer. | ||
| 701 | * If a receive overrun (ROR) interrupt is there then we disable SSP, flag the | ||
| 702 | * current message's state as STATE_ERROR and schedule the tasklet | ||
| 703 | * pump_transfers which will do the postprocessing of the current message by | ||
| 704 | * calling giveback(). Otherwise it reads data from RX FIFO till there is no | ||
| 705 | * more data, and writes data in TX FIFO till it is not full. If we complete | ||
| 706 | * the transfer we move to the next transfer and schedule the tasklet. | ||
| 707 | */ | ||
| 708 | static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id) | ||
| 709 | { | ||
| 710 | struct pl022 *pl022 = dev_id; | ||
| 711 | struct spi_message *msg = pl022->cur_msg; | ||
| 712 | u16 irq_status = 0; | ||
| 713 | u16 flag = 0; | ||
| 714 | |||
| 715 | if (unlikely(!msg)) { | ||
| 716 | dev_err(&pl022->adev->dev, | ||
| 717 | "bad message state in interrupt handler"); | ||
| 718 | /* Never fail */ | ||
| 719 | return IRQ_HANDLED; | ||
| 720 | } | ||
| 721 | |||
| 722 | /* Read the Interrupt Status Register */ | ||
| 723 | irq_status = readw(SSP_MIS(pl022->virtbase)); | ||
| 724 | |||
| 725 | if (unlikely(!irq_status)) | ||
| 726 | return IRQ_NONE; | ||
| 727 | |||
| 728 | /* This handles the error code interrupts */ | ||
| 729 | if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) { | ||
| 730 | /* | ||
| 731 | * Overrun interrupt - bail out since our Data has been | ||
| 732 | * corrupted | ||
| 733 | */ | ||
| 734 | dev_err(&pl022->adev->dev, | ||
| 735 | "FIFO overrun\n"); | ||
| 736 | if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF) | ||
| 737 | dev_err(&pl022->adev->dev, | ||
| 738 | "RXFIFO is full\n"); | ||
| 739 | if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF) | ||
| 740 | dev_err(&pl022->adev->dev, | ||
| 741 | "TXFIFO is full\n"); | ||
| 742 | |||
| 743 | /* | ||
| 744 | * Disable and clear interrupts, disable SSP, | ||
| 745 | * mark message with bad status so it can be | ||
| 746 | * retried. | ||
| 747 | */ | ||
| 748 | writew(DISABLE_ALL_INTERRUPTS, | ||
| 749 | SSP_IMSC(pl022->virtbase)); | ||
| 750 | writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); | ||
| 751 | writew((readw(SSP_CR1(pl022->virtbase)) & | ||
| 752 | (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); | ||
| 753 | msg->state = STATE_ERROR; | ||
| 754 | |||
| 755 | /* Schedule message queue handler */ | ||
| 756 | tasklet_schedule(&pl022->pump_transfers); | ||
| 757 | return IRQ_HANDLED; | ||
| 758 | } | ||
| 759 | |||
| 760 | readwriter(pl022); | ||
| 761 | |||
| 762 | if ((pl022->tx == pl022->tx_end) && (flag == 0)) { | ||
| 763 | flag = 1; | ||
| 764 | /* Disable Transmit interrupt */ | ||
| 765 | writew(readw(SSP_IMSC(pl022->virtbase)) & | ||
| 766 | (~SSP_IMSC_MASK_TXIM), | ||
| 767 | SSP_IMSC(pl022->virtbase)); | ||
| 768 | } | ||
| 769 | |||
| 770 | /* | ||
| 771 | * Since all transactions must write as much as shall be read, | ||
| 772 | * we can conclude the entire transaction once RX is complete. | ||
| 773 | * At this point, all TX will always be finished. | ||
| 774 | */ | ||
| 775 | if (pl022->rx >= pl022->rx_end) { | ||
| 776 | writew(DISABLE_ALL_INTERRUPTS, | ||
| 777 | SSP_IMSC(pl022->virtbase)); | ||
| 778 | writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); | ||
| 779 | if (unlikely(pl022->rx > pl022->rx_end)) { | ||
| 780 | dev_warn(&pl022->adev->dev, "read %u surplus " | ||
| 781 | "bytes (did you request an odd " | ||
| 782 | "number of bytes on a 16bit bus?)\n", | ||
| 783 | (u32) (pl022->rx - pl022->rx_end)); | ||
| 784 | } | ||
| 785 | /* Update total bytes transfered */ | ||
| 786 | msg->actual_length += pl022->cur_transfer->len; | ||
| 787 | if (pl022->cur_transfer->cs_change) | ||
| 788 | pl022->cur_chip-> | ||
| 789 | cs_control(SSP_CHIP_DESELECT); | ||
| 790 | /* Move to next transfer */ | ||
| 791 | msg->state = next_transfer(pl022); | ||
| 792 | tasklet_schedule(&pl022->pump_transfers); | ||
| 793 | return IRQ_HANDLED; | ||
| 794 | } | ||
| 795 | |||
| 796 | return IRQ_HANDLED; | ||
| 797 | } | ||
| 798 | |||
| 799 | /** | ||
| 800 | * This sets up the pointers to memory for the next message to | ||
| 801 | * send out on the SPI bus. | ||
| 802 | */ | ||
| 803 | static int set_up_next_transfer(struct pl022 *pl022, | ||
| 804 | struct spi_transfer *transfer) | ||
| 805 | { | ||
| 806 | int residue; | ||
| 807 | |||
| 808 | /* Sanity check the message for this bus width */ | ||
| 809 | residue = pl022->cur_transfer->len % pl022->cur_chip->n_bytes; | ||
| 810 | if (unlikely(residue != 0)) { | ||
| 811 | dev_err(&pl022->adev->dev, | ||
| 812 | "message of %u bytes to transmit but the current " | ||
| 813 | "chip bus has a data width of %u bytes!\n", | ||
| 814 | pl022->cur_transfer->len, | ||
| 815 | pl022->cur_chip->n_bytes); | ||
| 816 | dev_err(&pl022->adev->dev, "skipping this message\n"); | ||
| 817 | return -EIO; | ||
| 818 | } | ||
| 819 | pl022->tx = (void *)transfer->tx_buf; | ||
| 820 | pl022->tx_end = pl022->tx + pl022->cur_transfer->len; | ||
| 821 | pl022->rx = (void *)transfer->rx_buf; | ||
| 822 | pl022->rx_end = pl022->rx + pl022->cur_transfer->len; | ||
| 823 | pl022->write = | ||
| 824 | pl022->tx ? pl022->cur_chip->write : WRITING_NULL; | ||
| 825 | pl022->read = pl022->rx ? pl022->cur_chip->read : READING_NULL; | ||
| 826 | return 0; | ||
| 827 | } | ||
| 828 | |||
| 829 | /** | ||
| 830 | * pump_transfers - Tasklet function which schedules next interrupt transfer | ||
| 831 | * when running in interrupt transfer mode. | ||
| 832 | * @data: SSP driver private data structure | ||
| 833 | * | ||
| 834 | */ | ||
| 835 | static void pump_transfers(unsigned long data) | ||
| 836 | { | ||
| 837 | struct pl022 *pl022 = (struct pl022 *) data; | ||
| 838 | struct spi_message *message = NULL; | ||
| 839 | struct spi_transfer *transfer = NULL; | ||
| 840 | struct spi_transfer *previous = NULL; | ||
| 841 | |||
| 842 | /* Get current state information */ | ||
| 843 | message = pl022->cur_msg; | ||
| 844 | transfer = pl022->cur_transfer; | ||
| 845 | |||
| 846 | /* Handle for abort */ | ||
| 847 | if (message->state == STATE_ERROR) { | ||
| 848 | message->status = -EIO; | ||
| 849 | giveback(pl022); | ||
| 850 | return; | ||
| 851 | } | ||
| 852 | |||
| 853 | /* Handle end of message */ | ||
| 854 | if (message->state == STATE_DONE) { | ||
| 855 | message->status = 0; | ||
| 856 | giveback(pl022); | ||
| 857 | return; | ||
| 858 | } | ||
| 859 | |||
| 860 | /* Delay if requested at end of transfer before CS change */ | ||
| 861 | if (message->state == STATE_RUNNING) { | ||
| 862 | previous = list_entry(transfer->transfer_list.prev, | ||
| 863 | struct spi_transfer, | ||
| 864 | transfer_list); | ||
| 865 | if (previous->delay_usecs) | ||
| 866 | /* | ||
| 867 | * FIXME: This runs in interrupt context. | ||
| 868 | * Is this really smart? | ||
| 869 | */ | ||
| 870 | udelay(previous->delay_usecs); | ||
| 871 | |||
| 872 | /* Drop chip select only if cs_change is requested */ | ||
| 873 | if (previous->cs_change) | ||
| 874 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
| 875 | } else { | ||
| 876 | /* STATE_START */ | ||
| 877 | message->state = STATE_RUNNING; | ||
| 878 | } | ||
| 879 | |||
| 880 | if (set_up_next_transfer(pl022, transfer)) { | ||
| 881 | message->state = STATE_ERROR; | ||
| 882 | message->status = -EIO; | ||
| 883 | giveback(pl022); | ||
| 884 | return; | ||
| 885 | } | ||
| 886 | /* Flush the FIFOs and let's go! */ | ||
| 887 | flush(pl022); | ||
| 888 | writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | ||
| 889 | } | ||
| 890 | |||
| 891 | /** | ||
| 892 | * NOT IMPLEMENTED | ||
| 893 | * configure_dma - It configures the DMA pipes for DMA transfers | ||
| 894 | * @data: SSP driver's private data structure | ||
| 895 | * | ||
| 896 | */ | ||
| 897 | static int configure_dma(void *data) | ||
| 898 | { | ||
| 899 | struct pl022 *pl022 = data; | ||
| 900 | dev_dbg(&pl022->adev->dev, "configure DMA\n"); | ||
| 901 | return -ENOTSUPP; | ||
| 902 | } | ||
| 903 | |||
| 904 | /** | ||
| 905 | * do_dma_transfer - It handles transfers of the current message | ||
| 906 | * if it is DMA xfer. | ||
| 907 | * NOT FULLY IMPLEMENTED | ||
| 908 | * @data: SSP driver's private data structure | ||
| 909 | */ | ||
| 910 | static void do_dma_transfer(void *data) | ||
| 911 | { | ||
| 912 | struct pl022 *pl022 = data; | ||
| 913 | |||
| 914 | if (configure_dma(data)) { | ||
| 915 | dev_dbg(&pl022->adev->dev, "configuration of DMA Failed!\n"); | ||
| 916 | goto err_config_dma; | ||
| 917 | } | ||
| 918 | |||
| 919 | /* TODO: Implememt DMA setup of pipes here */ | ||
| 920 | |||
| 921 | /* Enable target chip, set up transfer */ | ||
| 922 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
| 923 | if (set_up_next_transfer(pl022, pl022->cur_transfer)) { | ||
| 924 | /* Error path */ | ||
| 925 | pl022->cur_msg->state = STATE_ERROR; | ||
| 926 | pl022->cur_msg->status = -EIO; | ||
| 927 | giveback(pl022); | ||
| 928 | return; | ||
| 929 | } | ||
| 930 | /* Enable SSP */ | ||
| 931 | writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), | ||
| 932 | SSP_CR1(pl022->virtbase)); | ||
| 933 | |||
| 934 | /* TODO: Enable the DMA transfer here */ | ||
| 935 | return; | ||
| 936 | |||
| 937 | err_config_dma: | ||
| 938 | pl022->cur_msg->state = STATE_ERROR; | ||
| 939 | pl022->cur_msg->status = -EIO; | ||
| 940 | giveback(pl022); | ||
| 941 | return; | ||
| 942 | } | ||
| 943 | |||
| 944 | static void do_interrupt_transfer(void *data) | ||
| 945 | { | ||
| 946 | struct pl022 *pl022 = data; | ||
| 947 | |||
| 948 | /* Enable target chip */ | ||
| 949 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
| 950 | if (set_up_next_transfer(pl022, pl022->cur_transfer)) { | ||
| 951 | /* Error path */ | ||
| 952 | pl022->cur_msg->state = STATE_ERROR; | ||
| 953 | pl022->cur_msg->status = -EIO; | ||
| 954 | giveback(pl022); | ||
| 955 | return; | ||
| 956 | } | ||
| 957 | /* Enable SSP, turn on interrupts */ | ||
| 958 | writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), | ||
| 959 | SSP_CR1(pl022->virtbase)); | ||
| 960 | writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | ||
| 961 | } | ||
| 962 | |||
| 963 | static void do_polling_transfer(void *data) | ||
| 964 | { | ||
| 965 | struct pl022 *pl022 = data; | ||
| 966 | struct spi_message *message = NULL; | ||
| 967 | struct spi_transfer *transfer = NULL; | ||
| 968 | struct spi_transfer *previous = NULL; | ||
| 969 | struct chip_data *chip; | ||
| 970 | |||
| 971 | chip = pl022->cur_chip; | ||
| 972 | message = pl022->cur_msg; | ||
| 973 | |||
| 974 | while (message->state != STATE_DONE) { | ||
| 975 | /* Handle for abort */ | ||
| 976 | if (message->state == STATE_ERROR) | ||
| 977 | break; | ||
| 978 | transfer = pl022->cur_transfer; | ||
| 979 | |||
| 980 | /* Delay if requested at end of transfer */ | ||
| 981 | if (message->state == STATE_RUNNING) { | ||
| 982 | previous = | ||
| 983 | list_entry(transfer->transfer_list.prev, | ||
| 984 | struct spi_transfer, transfer_list); | ||
| 985 | if (previous->delay_usecs) | ||
| 986 | udelay(previous->delay_usecs); | ||
| 987 | if (previous->cs_change) | ||
| 988 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
| 989 | } else { | ||
| 990 | /* STATE_START */ | ||
| 991 | message->state = STATE_RUNNING; | ||
| 992 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | ||
| 993 | } | ||
| 994 | |||
| 995 | /* Configuration Changing Per Transfer */ | ||
| 996 | if (set_up_next_transfer(pl022, transfer)) { | ||
| 997 | /* Error path */ | ||
| 998 | message->state = STATE_ERROR; | ||
| 999 | break; | ||
| 1000 | } | ||
| 1001 | /* Flush FIFOs and enable SSP */ | ||
| 1002 | flush(pl022); | ||
| 1003 | writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), | ||
| 1004 | SSP_CR1(pl022->virtbase)); | ||
| 1005 | |||
| 1006 | dev_dbg(&pl022->adev->dev, "POLLING TRANSFER ONGOING ... \n"); | ||
| 1007 | /* FIXME: insert a timeout so we don't hang here indefinately */ | ||
| 1008 | while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) | ||
| 1009 | readwriter(pl022); | ||
| 1010 | |||
| 1011 | /* Update total byte transfered */ | ||
| 1012 | message->actual_length += pl022->cur_transfer->len; | ||
| 1013 | if (pl022->cur_transfer->cs_change) | ||
| 1014 | pl022->cur_chip->cs_control(SSP_CHIP_DESELECT); | ||
| 1015 | /* Move to next transfer */ | ||
| 1016 | message->state = next_transfer(pl022); | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | /* Handle end of message */ | ||
| 1020 | if (message->state == STATE_DONE) | ||
| 1021 | message->status = 0; | ||
| 1022 | else | ||
| 1023 | message->status = -EIO; | ||
| 1024 | |||
| 1025 | giveback(pl022); | ||
| 1026 | return; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | /** | ||
| 1030 | * pump_messages - Workqueue function which processes spi message queue | ||
| 1031 | * @data: pointer to private data of SSP driver | ||
| 1032 | * | ||
| 1033 | * This function checks if there is any spi message in the queue that | ||
| 1034 | * needs processing and delegate control to appropriate function | ||
| 1035 | * do_polling_transfer()/do_interrupt_transfer()/do_dma_transfer() | ||
| 1036 | * based on the kind of the transfer | ||
| 1037 | * | ||
| 1038 | */ | ||
| 1039 | static void pump_messages(struct work_struct *work) | ||
| 1040 | { | ||
| 1041 | struct pl022 *pl022 = | ||
| 1042 | container_of(work, struct pl022, pump_messages); | ||
| 1043 | unsigned long flags; | ||
| 1044 | |||
| 1045 | /* Lock queue and check for queue work */ | ||
| 1046 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
| 1047 | if (list_empty(&pl022->queue) || pl022->run == QUEUE_STOPPED) { | ||
| 1048 | pl022->busy = 0; | ||
| 1049 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 1050 | return; | ||
| 1051 | } | ||
| 1052 | /* Make sure we are not already running a message */ | ||
| 1053 | if (pl022->cur_msg) { | ||
| 1054 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 1055 | return; | ||
| 1056 | } | ||
| 1057 | /* Extract head of queue */ | ||
| 1058 | pl022->cur_msg = | ||
| 1059 | list_entry(pl022->queue.next, struct spi_message, queue); | ||
| 1060 | |||
| 1061 | list_del_init(&pl022->cur_msg->queue); | ||
| 1062 | pl022->busy = 1; | ||
| 1063 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 1064 | |||
| 1065 | /* Initial message state */ | ||
| 1066 | pl022->cur_msg->state = STATE_START; | ||
| 1067 | pl022->cur_transfer = list_entry(pl022->cur_msg->transfers.next, | ||
| 1068 | struct spi_transfer, | ||
| 1069 | transfer_list); | ||
| 1070 | |||
| 1071 | /* Setup the SPI using the per chip configuration */ | ||
| 1072 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); | ||
| 1073 | /* | ||
| 1074 | * We enable the clock here, then the clock will be disabled when | ||
| 1075 | * giveback() is called in each method (poll/interrupt/DMA) | ||
| 1076 | */ | ||
| 1077 | clk_enable(pl022->clk); | ||
| 1078 | restore_state(pl022); | ||
| 1079 | flush(pl022); | ||
| 1080 | |||
| 1081 | if (pl022->cur_chip->xfer_type == POLLING_TRANSFER) | ||
| 1082 | do_polling_transfer(pl022); | ||
| 1083 | else if (pl022->cur_chip->xfer_type == INTERRUPT_TRANSFER) | ||
| 1084 | do_interrupt_transfer(pl022); | ||
| 1085 | else | ||
| 1086 | do_dma_transfer(pl022); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | |||
| 1090 | static int __init init_queue(struct pl022 *pl022) | ||
| 1091 | { | ||
| 1092 | INIT_LIST_HEAD(&pl022->queue); | ||
| 1093 | spin_lock_init(&pl022->queue_lock); | ||
| 1094 | |||
| 1095 | pl022->run = QUEUE_STOPPED; | ||
| 1096 | pl022->busy = 0; | ||
| 1097 | |||
| 1098 | tasklet_init(&pl022->pump_transfers, | ||
| 1099 | pump_transfers, (unsigned long)pl022); | ||
| 1100 | |||
| 1101 | INIT_WORK(&pl022->pump_messages, pump_messages); | ||
| 1102 | pl022->workqueue = create_singlethread_workqueue( | ||
| 1103 | dev_name(pl022->master->dev.parent)); | ||
| 1104 | if (pl022->workqueue == NULL) | ||
| 1105 | return -EBUSY; | ||
| 1106 | |||
| 1107 | return 0; | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | |||
| 1111 | static int start_queue(struct pl022 *pl022) | ||
| 1112 | { | ||
| 1113 | unsigned long flags; | ||
| 1114 | |||
| 1115 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
| 1116 | |||
| 1117 | if (pl022->run == QUEUE_RUNNING || pl022->busy) { | ||
| 1118 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 1119 | return -EBUSY; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | pl022->run = QUEUE_RUNNING; | ||
| 1123 | pl022->cur_msg = NULL; | ||
| 1124 | pl022->cur_transfer = NULL; | ||
| 1125 | pl022->cur_chip = NULL; | ||
| 1126 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 1127 | |||
| 1128 | queue_work(pl022->workqueue, &pl022->pump_messages); | ||
| 1129 | |||
| 1130 | return 0; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | |||
| 1134 | static int stop_queue(struct pl022 *pl022) | ||
| 1135 | { | ||
| 1136 | unsigned long flags; | ||
| 1137 | unsigned limit = 500; | ||
| 1138 | int status = 0; | ||
| 1139 | |||
| 1140 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
| 1141 | |||
| 1142 | /* This is a bit lame, but is optimized for the common execution path. | ||
| 1143 | * A wait_queue on the pl022->busy could be used, but then the common | ||
| 1144 | * execution path (pump_messages) would be required to call wake_up or | ||
| 1145 | * friends on every SPI message. Do this instead */ | ||
| 1146 | pl022->run = QUEUE_STOPPED; | ||
| 1147 | while (!list_empty(&pl022->queue) && pl022->busy && limit--) { | ||
| 1148 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 1149 | msleep(10); | ||
| 1150 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | if (!list_empty(&pl022->queue) || pl022->busy) | ||
| 1154 | status = -EBUSY; | ||
| 1155 | |||
| 1156 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 1157 | |||
| 1158 | return status; | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | static int destroy_queue(struct pl022 *pl022) | ||
| 1162 | { | ||
| 1163 | int status; | ||
| 1164 | |||
| 1165 | status = stop_queue(pl022); | ||
| 1166 | /* we are unloading the module or failing to load (only two calls | ||
| 1167 | * to this routine), and neither call can handle a return value. | ||
| 1168 | * However, destroy_workqueue calls flush_workqueue, and that will | ||
| 1169 | * block until all work is done. If the reason that stop_queue | ||
| 1170 | * timed out is that the work will never finish, then it does no | ||
| 1171 | * good to call destroy_workqueue, so return anyway. */ | ||
| 1172 | if (status != 0) | ||
| 1173 | return status; | ||
| 1174 | |||
| 1175 | destroy_workqueue(pl022->workqueue); | ||
| 1176 | |||
| 1177 | return 0; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | static int verify_controller_parameters(struct pl022 *pl022, | ||
| 1181 | struct pl022_config_chip *chip_info) | ||
| 1182 | { | ||
| 1183 | if ((chip_info->lbm != LOOPBACK_ENABLED) | ||
| 1184 | && (chip_info->lbm != LOOPBACK_DISABLED)) { | ||
| 1185 | dev_err(chip_info->dev, | ||
| 1186 | "loopback Mode is configured incorrectly\n"); | ||
| 1187 | return -EINVAL; | ||
| 1188 | } | ||
| 1189 | if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI) | ||
| 1190 | || (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) { | ||
| 1191 | dev_err(chip_info->dev, | ||
| 1192 | "interface is configured incorrectly\n"); | ||
| 1193 | return -EINVAL; | ||
| 1194 | } | ||
| 1195 | if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) && | ||
| 1196 | (!pl022->vendor->unidir)) { | ||
| 1197 | dev_err(chip_info->dev, | ||
| 1198 | "unidirectional mode not supported in this " | ||
| 1199 | "hardware version\n"); | ||
| 1200 | return -EINVAL; | ||
| 1201 | } | ||
| 1202 | if ((chip_info->hierarchy != SSP_MASTER) | ||
| 1203 | && (chip_info->hierarchy != SSP_SLAVE)) { | ||
| 1204 | dev_err(chip_info->dev, | ||
| 1205 | "hierarchy is configured incorrectly\n"); | ||
| 1206 | return -EINVAL; | ||
| 1207 | } | ||
| 1208 | if (((chip_info->clk_freq).cpsdvsr < CPSDVR_MIN) | ||
| 1209 | || ((chip_info->clk_freq).cpsdvsr > CPSDVR_MAX)) { | ||
| 1210 | dev_err(chip_info->dev, | ||
| 1211 | "cpsdvsr is configured incorrectly\n"); | ||
| 1212 | return -EINVAL; | ||
| 1213 | } | ||
| 1214 | if ((chip_info->endian_rx != SSP_RX_MSB) | ||
| 1215 | && (chip_info->endian_rx != SSP_RX_LSB)) { | ||
| 1216 | dev_err(chip_info->dev, | ||
| 1217 | "RX FIFO endianess is configured incorrectly\n"); | ||
| 1218 | return -EINVAL; | ||
| 1219 | } | ||
| 1220 | if ((chip_info->endian_tx != SSP_TX_MSB) | ||
| 1221 | && (chip_info->endian_tx != SSP_TX_LSB)) { | ||
| 1222 | dev_err(chip_info->dev, | ||
| 1223 | "TX FIFO endianess is configured incorrectly\n"); | ||
| 1224 | return -EINVAL; | ||
| 1225 | } | ||
| 1226 | if ((chip_info->data_size < SSP_DATA_BITS_4) | ||
| 1227 | || (chip_info->data_size > SSP_DATA_BITS_32)) { | ||
| 1228 | dev_err(chip_info->dev, | ||
| 1229 | "DATA Size is configured incorrectly\n"); | ||
| 1230 | return -EINVAL; | ||
| 1231 | } | ||
| 1232 | if ((chip_info->com_mode != INTERRUPT_TRANSFER) | ||
| 1233 | && (chip_info->com_mode != DMA_TRANSFER) | ||
| 1234 | && (chip_info->com_mode != POLLING_TRANSFER)) { | ||
| 1235 | dev_err(chip_info->dev, | ||
| 1236 | "Communication mode is configured incorrectly\n"); | ||
| 1237 | return -EINVAL; | ||
| 1238 | } | ||
| 1239 | if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM) | ||
| 1240 | || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) { | ||
| 1241 | dev_err(chip_info->dev, | ||
| 1242 | "RX FIFO Trigger Level is configured incorrectly\n"); | ||
| 1243 | return -EINVAL; | ||
| 1244 | } | ||
| 1245 | if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC) | ||
| 1246 | || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) { | ||
| 1247 | dev_err(chip_info->dev, | ||
| 1248 | "TX FIFO Trigger Level is configured incorrectly\n"); | ||
| 1249 | return -EINVAL; | ||
| 1250 | } | ||
| 1251 | if (chip_info->iface == SSP_INTERFACE_MOTOROLA_SPI) { | ||
| 1252 | if ((chip_info->clk_phase != SSP_CLK_RISING_EDGE) | ||
| 1253 | && (chip_info->clk_phase != SSP_CLK_FALLING_EDGE)) { | ||
| 1254 | dev_err(chip_info->dev, | ||
| 1255 | "Clock Phase is configured incorrectly\n"); | ||
| 1256 | return -EINVAL; | ||
| 1257 | } | ||
| 1258 | if ((chip_info->clk_pol != SSP_CLK_POL_IDLE_LOW) | ||
| 1259 | && (chip_info->clk_pol != SSP_CLK_POL_IDLE_HIGH)) { | ||
| 1260 | dev_err(chip_info->dev, | ||
| 1261 | "Clock Polarity is configured incorrectly\n"); | ||
| 1262 | return -EINVAL; | ||
| 1263 | } | ||
| 1264 | } | ||
| 1265 | if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) { | ||
| 1266 | if ((chip_info->ctrl_len < SSP_BITS_4) | ||
| 1267 | || (chip_info->ctrl_len > SSP_BITS_32)) { | ||
| 1268 | dev_err(chip_info->dev, | ||
| 1269 | "CTRL LEN is configured incorrectly\n"); | ||
| 1270 | return -EINVAL; | ||
| 1271 | } | ||
| 1272 | if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO) | ||
| 1273 | && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) { | ||
| 1274 | dev_err(chip_info->dev, | ||
| 1275 | "Wait State is configured incorrectly\n"); | ||
| 1276 | return -EINVAL; | ||
| 1277 | } | ||
| 1278 | if ((chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX) | ||
| 1279 | && (chip_info->duplex != | ||
| 1280 | SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) { | ||
| 1281 | dev_err(chip_info->dev, | ||
| 1282 | "DUPLEX is configured incorrectly\n"); | ||
| 1283 | return -EINVAL; | ||
| 1284 | } | ||
| 1285 | } | ||
| 1286 | if (chip_info->cs_control == NULL) { | ||
| 1287 | dev_warn(chip_info->dev, | ||
| 1288 | "Chip Select Function is NULL for this chip\n"); | ||
| 1289 | chip_info->cs_control = null_cs_control; | ||
| 1290 | } | ||
| 1291 | return 0; | ||
| 1292 | } | ||
| 1293 | |||
| 1294 | /** | ||
| 1295 | * pl022_transfer - transfer function registered to SPI master framework | ||
| 1296 | * @spi: spi device which is requesting transfer | ||
| 1297 | * @msg: spi message which is to handled is queued to driver queue | ||
| 1298 | * | ||
| 1299 | * This function is registered to the SPI framework for this SPI master | ||
| 1300 | * controller. It will queue the spi_message in the queue of driver if | ||
| 1301 | * the queue is not stopped and return. | ||
| 1302 | */ | ||
| 1303 | static int pl022_transfer(struct spi_device *spi, struct spi_message *msg) | ||
| 1304 | { | ||
| 1305 | struct pl022 *pl022 = spi_master_get_devdata(spi->master); | ||
| 1306 | unsigned long flags; | ||
| 1307 | |||
| 1308 | spin_lock_irqsave(&pl022->queue_lock, flags); | ||
| 1309 | |||
| 1310 | if (pl022->run == QUEUE_STOPPED) { | ||
| 1311 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 1312 | return -ESHUTDOWN; | ||
| 1313 | } | ||
| 1314 | msg->actual_length = 0; | ||
| 1315 | msg->status = -EINPROGRESS; | ||
| 1316 | msg->state = STATE_START; | ||
| 1317 | |||
| 1318 | list_add_tail(&msg->queue, &pl022->queue); | ||
| 1319 | if (pl022->run == QUEUE_RUNNING && !pl022->busy) | ||
| 1320 | queue_work(pl022->workqueue, &pl022->pump_messages); | ||
| 1321 | |||
| 1322 | spin_unlock_irqrestore(&pl022->queue_lock, flags); | ||
| 1323 | return 0; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | static int calculate_effective_freq(struct pl022 *pl022, | ||
| 1327 | int freq, | ||
| 1328 | struct ssp_clock_params *clk_freq) | ||
| 1329 | { | ||
| 1330 | /* Lets calculate the frequency parameters */ | ||
| 1331 | u16 cpsdvsr = 2; | ||
| 1332 | u16 scr = 0; | ||
| 1333 | bool freq_found = false; | ||
| 1334 | u32 rate; | ||
| 1335 | u32 max_tclk; | ||
| 1336 | u32 min_tclk; | ||
| 1337 | |||
| 1338 | rate = clk_get_rate(pl022->clk); | ||
| 1339 | /* cpsdvscr = 2 & scr 0 */ | ||
| 1340 | max_tclk = (rate / (CPSDVR_MIN * (1 + SCR_MIN))); | ||
| 1341 | /* cpsdvsr = 254 & scr = 255 */ | ||
| 1342 | min_tclk = (rate / (CPSDVR_MAX * (1 + SCR_MAX))); | ||
| 1343 | |||
| 1344 | if ((freq <= max_tclk) && (freq >= min_tclk)) { | ||
| 1345 | while (cpsdvsr <= CPSDVR_MAX && !freq_found) { | ||
| 1346 | while (scr <= SCR_MAX && !freq_found) { | ||
| 1347 | if ((rate / | ||
| 1348 | (cpsdvsr * (1 + scr))) > freq) | ||
| 1349 | scr += 1; | ||
| 1350 | else { | ||
| 1351 | /* | ||
| 1352 | * This bool is made true when | ||
| 1353 | * effective frequency >= | ||
| 1354 | * target frequency is found | ||
| 1355 | */ | ||
| 1356 | freq_found = true; | ||
| 1357 | if ((rate / | ||
| 1358 | (cpsdvsr * (1 + scr))) != freq) { | ||
| 1359 | if (scr == SCR_MIN) { | ||
| 1360 | cpsdvsr -= 2; | ||
| 1361 | scr = SCR_MAX; | ||
| 1362 | } else | ||
| 1363 | scr -= 1; | ||
| 1364 | } | ||
| 1365 | } | ||
| 1366 | } | ||
| 1367 | if (!freq_found) { | ||
| 1368 | cpsdvsr += 2; | ||
| 1369 | scr = SCR_MIN; | ||
| 1370 | } | ||
| 1371 | } | ||
| 1372 | if (cpsdvsr != 0) { | ||
| 1373 | dev_dbg(&pl022->adev->dev, | ||
| 1374 | "SSP Effective Frequency is %u\n", | ||
| 1375 | (rate / (cpsdvsr * (1 + scr)))); | ||
| 1376 | clk_freq->cpsdvsr = (u8) (cpsdvsr & 0xFF); | ||
| 1377 | clk_freq->scr = (u8) (scr & 0xFF); | ||
| 1378 | dev_dbg(&pl022->adev->dev, | ||
| 1379 | "SSP cpsdvsr = %d, scr = %d\n", | ||
| 1380 | clk_freq->cpsdvsr, clk_freq->scr); | ||
| 1381 | } | ||
| 1382 | } else { | ||
| 1383 | dev_err(&pl022->adev->dev, | ||
| 1384 | "controller data is incorrect: out of range frequency"); | ||
| 1385 | return -EINVAL; | ||
| 1386 | } | ||
| 1387 | return 0; | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | /** | ||
| 1391 | * NOT IMPLEMENTED | ||
| 1392 | * process_dma_info - Processes the DMA info provided by client drivers | ||
| 1393 | * @chip_info: chip info provided by client device | ||
| 1394 | * @chip: Runtime state maintained by the SSP controller for each spi device | ||
| 1395 | * | ||
| 1396 | * This function processes and stores DMA config provided by client driver | ||
| 1397 | * into the runtime state maintained by the SSP controller driver | ||
| 1398 | */ | ||
| 1399 | static int process_dma_info(struct pl022_config_chip *chip_info, | ||
| 1400 | struct chip_data *chip) | ||
| 1401 | { | ||
| 1402 | dev_err(chip_info->dev, | ||
| 1403 | "cannot process DMA info, DMA not implemented!\n"); | ||
| 1404 | return -ENOTSUPP; | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | /** | ||
| 1408 | * pl022_setup - setup function registered to SPI master framework | ||
| 1409 | * @spi: spi device which is requesting setup | ||
| 1410 | * | ||
| 1411 | * This function is registered to the SPI framework for this SPI master | ||
| 1412 | * controller. If it is the first time when setup is called by this device, | ||
| 1413 | * this function will initialize the runtime state for this chip and save | ||
| 1414 | * the same in the device structure. Else it will update the runtime info | ||
| 1415 | * with the updated chip info. Nothing is really being written to the | ||
| 1416 | * controller hardware here, that is not done until the actual transfer | ||
| 1417 | * commence. | ||
| 1418 | */ | ||
| 1419 | |||
| 1420 | /* FIXME: JUST GUESSING the spi->mode bits understood by this driver */ | ||
| 1421 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ | ||
| 1422 | | SPI_LSB_FIRST | SPI_LOOP) | ||
| 1423 | |||
| 1424 | static int pl022_setup(struct spi_device *spi) | ||
| 1425 | { | ||
| 1426 | struct pl022_config_chip *chip_info; | ||
| 1427 | struct chip_data *chip; | ||
| 1428 | int status = 0; | ||
| 1429 | struct pl022 *pl022 = spi_master_get_devdata(spi->master); | ||
| 1430 | |||
| 1431 | if (spi->mode & ~MODEBITS) { | ||
| 1432 | dev_dbg(&spi->dev, "unsupported mode bits %x\n", | ||
| 1433 | spi->mode & ~MODEBITS); | ||
| 1434 | return -EINVAL; | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | if (!spi->max_speed_hz) | ||
| 1438 | return -EINVAL; | ||
| 1439 | |||
| 1440 | /* Get controller_state if one is supplied */ | ||
| 1441 | chip = spi_get_ctldata(spi); | ||
| 1442 | |||
| 1443 | if (chip == NULL) { | ||
| 1444 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); | ||
| 1445 | if (!chip) { | ||
| 1446 | dev_err(&spi->dev, | ||
| 1447 | "cannot allocate controller state\n"); | ||
| 1448 | return -ENOMEM; | ||
| 1449 | } | ||
| 1450 | dev_dbg(&spi->dev, | ||
| 1451 | "allocated memory for controller's runtime state\n"); | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | /* Get controller data if one is supplied */ | ||
| 1455 | chip_info = spi->controller_data; | ||
| 1456 | |||
| 1457 | if (chip_info == NULL) { | ||
| 1458 | /* spi_board_info.controller_data not is supplied */ | ||
| 1459 | dev_dbg(&spi->dev, | ||
| 1460 | "using default controller_data settings\n"); | ||
| 1461 | |||
| 1462 | chip_info = | ||
| 1463 | kzalloc(sizeof(struct pl022_config_chip), GFP_KERNEL); | ||
| 1464 | |||
| 1465 | if (!chip_info) { | ||
| 1466 | dev_err(&spi->dev, | ||
| 1467 | "cannot allocate controller data\n"); | ||
| 1468 | status = -ENOMEM; | ||
| 1469 | goto err_first_setup; | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | dev_dbg(&spi->dev, "allocated memory for controller data\n"); | ||
| 1473 | |||
| 1474 | /* Pointer back to the SPI device */ | ||
| 1475 | chip_info->dev = &spi->dev; | ||
| 1476 | /* | ||
| 1477 | * Set controller data default values: | ||
| 1478 | * Polling is supported by default | ||
| 1479 | */ | ||
| 1480 | chip_info->lbm = LOOPBACK_DISABLED; | ||
| 1481 | chip_info->com_mode = POLLING_TRANSFER; | ||
| 1482 | chip_info->iface = SSP_INTERFACE_MOTOROLA_SPI; | ||
| 1483 | chip_info->hierarchy = SSP_SLAVE; | ||
| 1484 | chip_info->slave_tx_disable = DO_NOT_DRIVE_TX; | ||
| 1485 | chip_info->endian_tx = SSP_TX_LSB; | ||
| 1486 | chip_info->endian_rx = SSP_RX_LSB; | ||
| 1487 | chip_info->data_size = SSP_DATA_BITS_12; | ||
| 1488 | chip_info->rx_lev_trig = SSP_RX_1_OR_MORE_ELEM; | ||
| 1489 | chip_info->tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC; | ||
| 1490 | chip_info->clk_phase = SSP_CLK_FALLING_EDGE; | ||
| 1491 | chip_info->clk_pol = SSP_CLK_POL_IDLE_LOW; | ||
| 1492 | chip_info->ctrl_len = SSP_BITS_8; | ||
| 1493 | chip_info->wait_state = SSP_MWIRE_WAIT_ZERO; | ||
| 1494 | chip_info->duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX; | ||
| 1495 | chip_info->cs_control = null_cs_control; | ||
| 1496 | } else { | ||
| 1497 | dev_dbg(&spi->dev, | ||
| 1498 | "using user supplied controller_data settings\n"); | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | /* | ||
| 1502 | * We can override with custom divisors, else we use the board | ||
| 1503 | * frequency setting | ||
| 1504 | */ | ||
| 1505 | if ((0 == chip_info->clk_freq.cpsdvsr) | ||
| 1506 | && (0 == chip_info->clk_freq.scr)) { | ||
| 1507 | status = calculate_effective_freq(pl022, | ||
| 1508 | spi->max_speed_hz, | ||
| 1509 | &chip_info->clk_freq); | ||
| 1510 | if (status < 0) | ||
| 1511 | goto err_config_params; | ||
| 1512 | } else { | ||
| 1513 | if ((chip_info->clk_freq.cpsdvsr % 2) != 0) | ||
| 1514 | chip_info->clk_freq.cpsdvsr = | ||
| 1515 | chip_info->clk_freq.cpsdvsr - 1; | ||
| 1516 | } | ||
| 1517 | status = verify_controller_parameters(pl022, chip_info); | ||
| 1518 | if (status) { | ||
| 1519 | dev_err(&spi->dev, "controller data is incorrect"); | ||
| 1520 | goto err_config_params; | ||
| 1521 | } | ||
| 1522 | /* Now set controller state based on controller data */ | ||
| 1523 | chip->xfer_type = chip_info->com_mode; | ||
| 1524 | chip->cs_control = chip_info->cs_control; | ||
| 1525 | |||
| 1526 | if (chip_info->data_size <= 8) { | ||
| 1527 | dev_dbg(&spi->dev, "1 <= n <=8 bits per word\n"); | ||
| 1528 | chip->n_bytes = 1; | ||
| 1529 | chip->read = READING_U8; | ||
| 1530 | chip->write = WRITING_U8; | ||
| 1531 | } else if (chip_info->data_size <= 16) { | ||
| 1532 | dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n"); | ||
| 1533 | chip->n_bytes = 2; | ||
| 1534 | chip->read = READING_U16; | ||
| 1535 | chip->write = WRITING_U16; | ||
| 1536 | } else { | ||
| 1537 | if (pl022->vendor->max_bpw >= 32) { | ||
| 1538 | dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n"); | ||
| 1539 | chip->n_bytes = 4; | ||
| 1540 | chip->read = READING_U32; | ||
| 1541 | chip->write = WRITING_U32; | ||
| 1542 | } else { | ||
| 1543 | dev_err(&spi->dev, | ||
| 1544 | "illegal data size for this controller!\n"); | ||
| 1545 | dev_err(&spi->dev, | ||
| 1546 | "a standard pl022 can only handle " | ||
| 1547 | "1 <= n <= 16 bit words\n"); | ||
| 1548 | goto err_config_params; | ||
| 1549 | } | ||
| 1550 | } | ||
| 1551 | |||
| 1552 | /* Now Initialize all register settings required for this chip */ | ||
| 1553 | chip->cr0 = 0; | ||
| 1554 | chip->cr1 = 0; | ||
| 1555 | chip->dmacr = 0; | ||
| 1556 | chip->cpsr = 0; | ||
| 1557 | if ((chip_info->com_mode == DMA_TRANSFER) | ||
| 1558 | && ((pl022->master_info)->enable_dma)) { | ||
| 1559 | chip->enable_dma = 1; | ||
| 1560 | dev_dbg(&spi->dev, "DMA mode set in controller state\n"); | ||
| 1561 | status = process_dma_info(chip_info, chip); | ||
| 1562 | if (status < 0) | ||
| 1563 | goto err_config_params; | ||
| 1564 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, | ||
| 1565 | SSP_DMACR_MASK_RXDMAE, 0); | ||
| 1566 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, | ||
| 1567 | SSP_DMACR_MASK_TXDMAE, 1); | ||
| 1568 | } else { | ||
| 1569 | chip->enable_dma = 0; | ||
| 1570 | dev_dbg(&spi->dev, "DMA mode NOT set in controller state\n"); | ||
| 1571 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED, | ||
| 1572 | SSP_DMACR_MASK_RXDMAE, 0); | ||
| 1573 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED, | ||
| 1574 | SSP_DMACR_MASK_TXDMAE, 1); | ||
| 1575 | } | ||
| 1576 | |||
| 1577 | chip->cpsr = chip_info->clk_freq.cpsdvsr; | ||
| 1578 | |||
| 1579 | SSP_WRITE_BITS(chip->cr0, chip_info->data_size, SSP_CR0_MASK_DSS, 0); | ||
| 1580 | SSP_WRITE_BITS(chip->cr0, chip_info->duplex, SSP_CR0_MASK_HALFDUP, 5); | ||
| 1581 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_pol, SSP_CR0_MASK_SPO, 6); | ||
| 1582 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_phase, SSP_CR0_MASK_SPH, 7); | ||
| 1583 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_freq.scr, SSP_CR0_MASK_SCR, 8); | ||
| 1584 | SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len, SSP_CR0_MASK_CSS, 16); | ||
| 1585 | SSP_WRITE_BITS(chip->cr0, chip_info->iface, SSP_CR0_MASK_FRF, 21); | ||
| 1586 | SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0); | ||
| 1587 | SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1); | ||
| 1588 | SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2); | ||
| 1589 | SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3); | ||
| 1590 | SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx, SSP_CR1_MASK_RENDN, 4); | ||
| 1591 | SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx, SSP_CR1_MASK_TENDN, 5); | ||
| 1592 | SSP_WRITE_BITS(chip->cr1, chip_info->wait_state, SSP_CR1_MASK_MWAIT, 6); | ||
| 1593 | SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig, SSP_CR1_MASK_RXIFLSEL, 7); | ||
| 1594 | SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig, SSP_CR1_MASK_TXIFLSEL, 10); | ||
| 1595 | |||
| 1596 | /* Save controller_state */ | ||
| 1597 | spi_set_ctldata(spi, chip); | ||
| 1598 | return status; | ||
| 1599 | err_config_params: | ||
| 1600 | err_first_setup: | ||
| 1601 | kfree(chip); | ||
| 1602 | return status; | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | /** | ||
| 1606 | * pl022_cleanup - cleanup function registered to SPI master framework | ||
| 1607 | * @spi: spi device which is requesting cleanup | ||
| 1608 | * | ||
| 1609 | * This function is registered to the SPI framework for this SPI master | ||
| 1610 | * controller. It will free the runtime state of chip. | ||
| 1611 | */ | ||
| 1612 | static void pl022_cleanup(struct spi_device *spi) | ||
| 1613 | { | ||
| 1614 | struct chip_data *chip = spi_get_ctldata(spi); | ||
| 1615 | |||
| 1616 | spi_set_ctldata(spi, NULL); | ||
| 1617 | kfree(chip); | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | |||
| 1621 | static int __init | ||
| 1622 | pl022_probe(struct amba_device *adev, struct amba_id *id) | ||
| 1623 | { | ||
| 1624 | struct device *dev = &adev->dev; | ||
| 1625 | struct pl022_ssp_controller *platform_info = adev->dev.platform_data; | ||
| 1626 | struct spi_master *master; | ||
| 1627 | struct pl022 *pl022 = NULL; /*Data for this driver */ | ||
| 1628 | int status = 0; | ||
| 1629 | |||
| 1630 | dev_info(&adev->dev, | ||
| 1631 | "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid); | ||
| 1632 | if (platform_info == NULL) { | ||
| 1633 | dev_err(&adev->dev, "probe - no platform data supplied\n"); | ||
| 1634 | status = -ENODEV; | ||
| 1635 | goto err_no_pdata; | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | /* Allocate master with space for data */ | ||
| 1639 | master = spi_alloc_master(dev, sizeof(struct pl022)); | ||
| 1640 | if (master == NULL) { | ||
| 1641 | dev_err(&adev->dev, "probe - cannot alloc SPI master\n"); | ||
| 1642 | status = -ENOMEM; | ||
| 1643 | goto err_no_master; | ||
| 1644 | } | ||
| 1645 | |||
| 1646 | pl022 = spi_master_get_devdata(master); | ||
| 1647 | pl022->master = master; | ||
| 1648 | pl022->master_info = platform_info; | ||
| 1649 | pl022->adev = adev; | ||
| 1650 | pl022->vendor = id->data; | ||
| 1651 | |||
| 1652 | /* | ||
| 1653 | * Bus Number Which has been Assigned to this SSP controller | ||
| 1654 | * on this board | ||
| 1655 | */ | ||
| 1656 | master->bus_num = platform_info->bus_id; | ||
| 1657 | master->num_chipselect = platform_info->num_chipselect; | ||
| 1658 | master->cleanup = pl022_cleanup; | ||
| 1659 | master->setup = pl022_setup; | ||
| 1660 | master->transfer = pl022_transfer; | ||
| 1661 | |||
| 1662 | dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num); | ||
| 1663 | |||
| 1664 | status = amba_request_regions(adev, NULL); | ||
| 1665 | if (status) | ||
| 1666 | goto err_no_ioregion; | ||
| 1667 | |||
| 1668 | pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res)); | ||
| 1669 | if (pl022->virtbase == NULL) { | ||
| 1670 | status = -ENOMEM; | ||
| 1671 | goto err_no_ioremap; | ||
| 1672 | } | ||
| 1673 | printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", | ||
| 1674 | adev->res.start, pl022->virtbase); | ||
| 1675 | |||
| 1676 | pl022->clk = clk_get(&adev->dev, NULL); | ||
| 1677 | if (IS_ERR(pl022->clk)) { | ||
| 1678 | status = PTR_ERR(pl022->clk); | ||
| 1679 | dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n"); | ||
| 1680 | goto err_no_clk; | ||
| 1681 | } | ||
| 1682 | |||
| 1683 | /* Disable SSP */ | ||
| 1684 | clk_enable(pl022->clk); | ||
| 1685 | writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), | ||
| 1686 | SSP_CR1(pl022->virtbase)); | ||
| 1687 | load_ssp_default_config(pl022); | ||
| 1688 | clk_disable(pl022->clk); | ||
| 1689 | |||
| 1690 | status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022", | ||
| 1691 | pl022); | ||
| 1692 | if (status < 0) { | ||
| 1693 | dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status); | ||
| 1694 | goto err_no_irq; | ||
| 1695 | } | ||
| 1696 | /* Initialize and start queue */ | ||
| 1697 | status = init_queue(pl022); | ||
| 1698 | if (status != 0) { | ||
| 1699 | dev_err(&adev->dev, "probe - problem initializing queue\n"); | ||
| 1700 | goto err_init_queue; | ||
| 1701 | } | ||
| 1702 | status = start_queue(pl022); | ||
| 1703 | if (status != 0) { | ||
| 1704 | dev_err(&adev->dev, "probe - problem starting queue\n"); | ||
| 1705 | goto err_start_queue; | ||
| 1706 | } | ||
| 1707 | /* Register with the SPI framework */ | ||
| 1708 | amba_set_drvdata(adev, pl022); | ||
| 1709 | status = spi_register_master(master); | ||
| 1710 | if (status != 0) { | ||
| 1711 | dev_err(&adev->dev, | ||
| 1712 | "probe - problem registering spi master\n"); | ||
| 1713 | goto err_spi_register; | ||
| 1714 | } | ||
| 1715 | dev_dbg(dev, "probe succeded\n"); | ||
| 1716 | return 0; | ||
| 1717 | |||
| 1718 | err_spi_register: | ||
| 1719 | err_start_queue: | ||
| 1720 | err_init_queue: | ||
| 1721 | destroy_queue(pl022); | ||
| 1722 | free_irq(adev->irq[0], pl022); | ||
| 1723 | err_no_irq: | ||
| 1724 | clk_put(pl022->clk); | ||
| 1725 | err_no_clk: | ||
| 1726 | iounmap(pl022->virtbase); | ||
| 1727 | err_no_ioremap: | ||
| 1728 | amba_release_regions(adev); | ||
| 1729 | err_no_ioregion: | ||
| 1730 | spi_master_put(master); | ||
| 1731 | err_no_master: | ||
| 1732 | err_no_pdata: | ||
| 1733 | return status; | ||
| 1734 | } | ||
| 1735 | |||
| 1736 | static int __exit | ||
| 1737 | pl022_remove(struct amba_device *adev) | ||
| 1738 | { | ||
| 1739 | struct pl022 *pl022 = amba_get_drvdata(adev); | ||
| 1740 | int status = 0; | ||
| 1741 | if (!pl022) | ||
| 1742 | return 0; | ||
| 1743 | |||
| 1744 | /* Remove the queue */ | ||
| 1745 | status = destroy_queue(pl022); | ||
| 1746 | if (status != 0) { | ||
| 1747 | dev_err(&adev->dev, | ||
| 1748 | "queue remove failed (%d)\n", status); | ||
| 1749 | return status; | ||
| 1750 | } | ||
| 1751 | load_ssp_default_config(pl022); | ||
| 1752 | free_irq(adev->irq[0], pl022); | ||
| 1753 | clk_disable(pl022->clk); | ||
| 1754 | clk_put(pl022->clk); | ||
| 1755 | iounmap(pl022->virtbase); | ||
| 1756 | amba_release_regions(adev); | ||
| 1757 | tasklet_disable(&pl022->pump_transfers); | ||
| 1758 | spi_unregister_master(pl022->master); | ||
| 1759 | spi_master_put(pl022->master); | ||
| 1760 | amba_set_drvdata(adev, NULL); | ||
| 1761 | dev_dbg(&adev->dev, "remove succeded\n"); | ||
| 1762 | return 0; | ||
| 1763 | } | ||
| 1764 | |||
| 1765 | #ifdef CONFIG_PM | ||
| 1766 | static int pl022_suspend(struct amba_device *adev, pm_message_t state) | ||
| 1767 | { | ||
| 1768 | struct pl022 *pl022 = amba_get_drvdata(adev); | ||
| 1769 | int status = 0; | ||
| 1770 | |||
| 1771 | status = stop_queue(pl022); | ||
| 1772 | if (status) { | ||
| 1773 | dev_warn(&adev->dev, "suspend cannot stop queue\n"); | ||
| 1774 | return status; | ||
| 1775 | } | ||
| 1776 | |||
| 1777 | clk_enable(pl022->clk); | ||
| 1778 | load_ssp_default_config(pl022); | ||
| 1779 | clk_disable(pl022->clk); | ||
| 1780 | dev_dbg(&adev->dev, "suspended\n"); | ||
| 1781 | return 0; | ||
| 1782 | } | ||
| 1783 | |||
| 1784 | static int pl022_resume(struct amba_device *adev) | ||
| 1785 | { | ||
| 1786 | struct pl022 *pl022 = amba_get_drvdata(adev); | ||
| 1787 | int status = 0; | ||
| 1788 | |||
| 1789 | /* Start the queue running */ | ||
| 1790 | status = start_queue(pl022); | ||
| 1791 | if (status) | ||
| 1792 | dev_err(&adev->dev, "problem starting queue (%d)\n", status); | ||
| 1793 | else | ||
| 1794 | dev_dbg(&adev->dev, "resumed\n"); | ||
| 1795 | |||
| 1796 | return status; | ||
| 1797 | } | ||
| 1798 | #else | ||
| 1799 | #define pl022_suspend NULL | ||
| 1800 | #define pl022_resume NULL | ||
| 1801 | #endif /* CONFIG_PM */ | ||
| 1802 | |||
| 1803 | static struct vendor_data vendor_arm = { | ||
| 1804 | .fifodepth = 8, | ||
| 1805 | .max_bpw = 16, | ||
| 1806 | .unidir = false, | ||
| 1807 | }; | ||
| 1808 | |||
| 1809 | |||
| 1810 | static struct vendor_data vendor_st = { | ||
| 1811 | .fifodepth = 32, | ||
| 1812 | .max_bpw = 32, | ||
| 1813 | .unidir = false, | ||
| 1814 | }; | ||
| 1815 | |||
| 1816 | static struct amba_id pl022_ids[] = { | ||
| 1817 | { | ||
| 1818 | /* | ||
| 1819 | * ARM PL022 variant, this has a 16bit wide | ||
| 1820 | * and 8 locations deep TX/RX FIFO | ||
| 1821 | */ | ||
| 1822 | .id = 0x00041022, | ||
| 1823 | .mask = 0x000fffff, | ||
| 1824 | .data = &vendor_arm, | ||
| 1825 | }, | ||
| 1826 | { | ||
| 1827 | /* | ||
| 1828 | * ST Micro derivative, this has 32bit wide | ||
| 1829 | * and 32 locations deep TX/RX FIFO | ||
| 1830 | */ | ||
| 1831 | .id = 0x00108022, | ||
| 1832 | .mask = 0xffffffff, | ||
| 1833 | .data = &vendor_st, | ||
| 1834 | }, | ||
| 1835 | { 0, 0 }, | ||
| 1836 | }; | ||
| 1837 | |||
| 1838 | static struct amba_driver pl022_driver = { | ||
| 1839 | .drv = { | ||
| 1840 | .name = "ssp-pl022", | ||
| 1841 | }, | ||
| 1842 | .id_table = pl022_ids, | ||
| 1843 | .probe = pl022_probe, | ||
| 1844 | .remove = __exit_p(pl022_remove), | ||
| 1845 | .suspend = pl022_suspend, | ||
| 1846 | .resume = pl022_resume, | ||
| 1847 | }; | ||
| 1848 | |||
| 1849 | |||
| 1850 | static int __init pl022_init(void) | ||
| 1851 | { | ||
| 1852 | return amba_driver_register(&pl022_driver); | ||
| 1853 | } | ||
| 1854 | |||
| 1855 | module_init(pl022_init); | ||
| 1856 | |||
| 1857 | static void __exit pl022_exit(void) | ||
| 1858 | { | ||
| 1859 | amba_driver_unregister(&pl022_driver); | ||
| 1860 | } | ||
| 1861 | |||
| 1862 | module_exit(pl022_exit); | ||
| 1863 | |||
| 1864 | MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); | ||
| 1865 | MODULE_DESCRIPTION("PL022 SSP Controller Driver"); | ||
| 1866 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c index f2447a5476bb..bbf9371cd284 100644 --- a/drivers/spi/spi_s3c24xx_gpio.c +++ b/drivers/spi/spi_s3c24xx_gpio.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
| 18 | #include <linux/workqueue.h> | 18 | #include <linux/workqueue.h> |
| 19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 20 | #include <linux/gpio.h> | ||
| 20 | 21 | ||
| 21 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
| 22 | #include <linux/spi/spi_bitbang.h> | 23 | #include <linux/spi/spi_bitbang.h> |
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 7cf74f8c2db1..b0dbf4157d29 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c | |||
| @@ -47,7 +47,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, | |||
| 47 | struct usb_hcd *hcd; | 47 | struct usb_hcd *hcd; |
| 48 | 48 | ||
| 49 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { | 49 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { |
| 50 | pr_debug("resource[1] is not IORESOURCE_IRQ"); | 50 | dbg("resource[1] is not IORESOURCE_IRQ"); |
| 51 | return -ENOMEM; | 51 | return -ENOMEM; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| @@ -65,12 +65,18 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, | |||
| 65 | 65 | ||
| 66 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | 66 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); |
| 67 | if (hcd->regs == NULL) { | 67 | if (hcd->regs == NULL) { |
| 68 | pr_debug("ioremap failed"); | 68 | dbg("ioremap failed"); |
| 69 | retval = -ENOMEM; | 69 | retval = -ENOMEM; |
| 70 | goto err2; | 70 | goto err2; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | usb_host_clock = clk_get(&pdev->dev, "usb_host"); | 73 | usb_host_clock = clk_get(&pdev->dev, NULL); |
| 74 | if (IS_ERR(usb_host_clock)) { | ||
| 75 | dbg("clk_get failed"); | ||
| 76 | retval = PTR_ERR(usb_host_clock); | ||
| 77 | goto err3; | ||
| 78 | } | ||
| 79 | |||
| 74 | ep93xx_start_hc(&pdev->dev); | 80 | ep93xx_start_hc(&pdev->dev); |
| 75 | 81 | ||
| 76 | ohci_hcd_init(hcd_to_ohci(hcd)); | 82 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| @@ -80,6 +86,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, | |||
| 80 | return retval; | 86 | return retval; |
| 81 | 87 | ||
| 82 | ep93xx_stop_hc(&pdev->dev); | 88 | ep93xx_stop_hc(&pdev->dev); |
| 89 | err3: | ||
| 83 | iounmap(hcd->regs); | 90 | iounmap(hcd->regs); |
| 84 | err2: | 91 | err2: |
| 85 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 92 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 74712cb8399a..2b5a691064b7 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -397,7 +397,7 @@ config FB_SA1100 | |||
| 397 | 397 | ||
| 398 | config FB_IMX | 398 | config FB_IMX |
| 399 | tristate "Motorola i.MX LCD support" | 399 | tristate "Motorola i.MX LCD support" |
| 400 | depends on FB && (ARCH_IMX || ARCH_MX2) | 400 | depends on FB && (ARCH_MX1 || ARCH_MX2) |
| 401 | select FB_CFB_FILLRECT | 401 | select FB_CFB_FILLRECT |
| 402 | select FB_CFB_COPYAREA | 402 | select FB_CFB_COPYAREA |
| 403 | select FB_CFB_IMAGEBLIT | 403 | select FB_CFB_IMAGEBLIT |
| @@ -1759,6 +1759,16 @@ config FB_68328 | |||
| 1759 | Say Y here if you want to support the built-in frame buffer of | 1759 | Say Y here if you want to support the built-in frame buffer of |
| 1760 | the Motorola 68328 CPU family. | 1760 | the Motorola 68328 CPU family. |
| 1761 | 1761 | ||
| 1762 | config FB_PXA168 | ||
| 1763 | tristate "PXA168/910 LCD framebuffer support" | ||
| 1764 | depends on FB && (CPU_PXA168 || CPU_PXA910) | ||
| 1765 | select FB_CFB_FILLRECT | ||
| 1766 | select FB_CFB_COPYAREA | ||
| 1767 | select FB_CFB_IMAGEBLIT | ||
| 1768 | ---help--- | ||
| 1769 | Frame buffer driver for the built-in LCD controller in the Marvell | ||
| 1770 | MMP processor. | ||
| 1771 | |||
| 1762 | config FB_PXA | 1772 | config FB_PXA |
| 1763 | tristate "PXA LCD framebuffer support" | 1773 | tristate "PXA LCD framebuffer support" |
| 1764 | depends on FB && ARCH_PXA | 1774 | depends on FB && ARCH_PXA |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index d8d0be5151e3..01a819f47371 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
| @@ -97,6 +97,7 @@ obj-$(CONFIG_FB_GBE) += gbefb.o | |||
| 97 | obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o | 97 | obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o |
| 98 | obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o | 98 | obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o |
| 99 | obj-$(CONFIG_FB_PXA) += pxafb.o | 99 | obj-$(CONFIG_FB_PXA) += pxafb.o |
| 100 | obj-$(CONFIG_FB_PXA168) += pxa168fb.o | ||
| 100 | obj-$(CONFIG_FB_W100) += w100fb.o | 101 | obj-$(CONFIG_FB_W100) += w100fb.o |
| 101 | obj-$(CONFIG_FB_TMIO) += tmiofb.o | 102 | obj-$(CONFIG_FB_TMIO) += tmiofb.o |
| 102 | obj-$(CONFIG_FB_AU1100) += au1100fb.o | 103 | obj-$(CONFIG_FB_AU1100) += au1100fb.o |
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index d1f80bac54f0..fb8163d181ab 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c | |||
| @@ -351,7 +351,7 @@ static int clcdfb_register(struct clcd_fb *fb) | |||
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | fb->fb.fix.mmio_start = fb->dev->res.start; | 353 | fb->fb.fix.mmio_start = fb->dev->res.start; |
| 354 | fb->fb.fix.mmio_len = 4096; | 354 | fb->fb.fix.mmio_len = resource_size(&fb->dev->res); |
| 355 | 355 | ||
| 356 | fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len); | 356 | fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len); |
| 357 | if (!fb->regs) { | 357 | if (!fb->regs) { |
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 9894de1c9b9f..b7af5256e887 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c | |||
| @@ -706,7 +706,7 @@ static void mx3fb_dma_done(void *arg) | |||
| 706 | dev_dbg(mx3fb->dev, "irq %d callback\n", ichannel->eof_irq); | 706 | dev_dbg(mx3fb->dev, "irq %d callback\n", ichannel->eof_irq); |
| 707 | 707 | ||
| 708 | /* We only need one interrupt, it will be re-enabled as needed */ | 708 | /* We only need one interrupt, it will be re-enabled as needed */ |
| 709 | disable_irq(ichannel->eof_irq); | 709 | disable_irq_nosync(ichannel->eof_irq); |
| 710 | 710 | ||
| 711 | complete(&mx3_fbi->flip_cmpl); | 711 | complete(&mx3_fbi->flip_cmpl); |
| 712 | } | 712 | } |
| @@ -1366,7 +1366,7 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) | |||
| 1366 | 1366 | ||
| 1367 | mx3fb_blank(FB_BLANK_UNBLANK, fbi); | 1367 | mx3fb_blank(FB_BLANK_UNBLANK, fbi); |
| 1368 | 1368 | ||
| 1369 | dev_info(dev, "mx3fb: fb registered, using mode %s\n", fb_mode); | 1369 | dev_info(dev, "registered, using mode %s\n", fb_mode); |
| 1370 | 1370 | ||
| 1371 | ret = register_framebuffer(fbi); | 1371 | ret = register_framebuffer(fbi); |
| 1372 | if (ret < 0) | 1372 | if (ret < 0) |
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index 8aa6e47202b9..5d4f34887a22 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c | |||
| @@ -133,8 +133,7 @@ struct { | |||
| 133 | struct lcd_ctrl_extif *extif; | 133 | struct lcd_ctrl_extif *extif; |
| 134 | struct lcd_ctrl *int_ctrl; | 134 | struct lcd_ctrl *int_ctrl; |
| 135 | 135 | ||
| 136 | void (*power_up)(struct device *dev); | 136 | struct clk *sys_ck; |
| 137 | void (*power_down)(struct device *dev); | ||
| 138 | } hwa742; | 137 | } hwa742; |
| 139 | 138 | ||
| 140 | struct lcd_ctrl hwa742_ctrl; | 139 | struct lcd_ctrl hwa742_ctrl; |
| @@ -915,14 +914,13 @@ static void hwa742_suspend(void) | |||
| 915 | hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); | 914 | hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); |
| 916 | /* Enable sleep mode */ | 915 | /* Enable sleep mode */ |
| 917 | hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1); | 916 | hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1); |
| 918 | if (hwa742.power_down != NULL) | 917 | clk_disable(hwa742.sys_ck); |
| 919 | hwa742.power_down(hwa742.fbdev->dev); | ||
| 920 | } | 918 | } |
| 921 | 919 | ||
| 922 | static void hwa742_resume(void) | 920 | static void hwa742_resume(void) |
| 923 | { | 921 | { |
| 924 | if (hwa742.power_up != NULL) | 922 | clk_enable(hwa742.sys_ck); |
| 925 | hwa742.power_up(hwa742.fbdev->dev); | 923 | |
| 926 | /* Disable sleep mode */ | 924 | /* Disable sleep mode */ |
| 927 | hwa742_write_reg(HWA742_POWER_SAVE, 0); | 925 | hwa742_write_reg(HWA742_POWER_SAVE, 0); |
| 928 | while (1) { | 926 | while (1) { |
| @@ -955,14 +953,13 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, | |||
| 955 | omapfb_conf = fbdev->dev->platform_data; | 953 | omapfb_conf = fbdev->dev->platform_data; |
| 956 | ctrl_conf = omapfb_conf->ctrl_platform_data; | 954 | ctrl_conf = omapfb_conf->ctrl_platform_data; |
| 957 | 955 | ||
| 958 | if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) { | 956 | if (ctrl_conf == NULL) { |
| 959 | dev_err(fbdev->dev, "HWA742: missing platform data\n"); | 957 | dev_err(fbdev->dev, "HWA742: missing platform data\n"); |
| 960 | r = -ENOENT; | 958 | r = -ENOENT; |
| 961 | goto err1; | 959 | goto err1; |
| 962 | } | 960 | } |
| 963 | 961 | ||
| 964 | hwa742.power_down = ctrl_conf->power_down; | 962 | hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck"); |
| 965 | hwa742.power_up = ctrl_conf->power_up; | ||
| 966 | 963 | ||
| 967 | spin_lock_init(&hwa742.req_lock); | 964 | spin_lock_init(&hwa742.req_lock); |
| 968 | 965 | ||
| @@ -972,12 +969,11 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, | |||
| 972 | if ((r = hwa742.extif->init(fbdev)) < 0) | 969 | if ((r = hwa742.extif->init(fbdev)) < 0) |
| 973 | goto err2; | 970 | goto err2; |
| 974 | 971 | ||
| 975 | ext_clk = ctrl_conf->get_clock_rate(fbdev->dev); | 972 | ext_clk = clk_get_rate(hwa742.sys_ck); |
| 976 | if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0) | 973 | if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0) |
| 977 | goto err3; | 974 | goto err3; |
| 978 | hwa742.extif->set_timings(&hwa742.reg_timings); | 975 | hwa742.extif->set_timings(&hwa742.reg_timings); |
| 979 | if (hwa742.power_up != NULL) | 976 | clk_enable(hwa742.sys_ck); |
| 980 | hwa742.power_up(fbdev->dev); | ||
| 981 | 977 | ||
| 982 | calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk); | 978 | calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk); |
| 983 | if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0) | 979 | if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0) |
| @@ -1040,8 +1036,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, | |||
| 1040 | 1036 | ||
| 1041 | return 0; | 1037 | return 0; |
| 1042 | err4: | 1038 | err4: |
| 1043 | if (hwa742.power_down != NULL) | 1039 | clk_disable(hwa742.sys_ck); |
| 1044 | hwa742.power_down(fbdev->dev); | ||
| 1045 | err3: | 1040 | err3: |
| 1046 | hwa742.extif->cleanup(); | 1041 | hwa742.extif->cleanup(); |
| 1047 | err2: | 1042 | err2: |
| @@ -1055,8 +1050,7 @@ static void hwa742_cleanup(void) | |||
| 1055 | hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); | 1050 | hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); |
| 1056 | hwa742.extif->cleanup(); | 1051 | hwa742.extif->cleanup(); |
| 1057 | hwa742.int_ctrl->cleanup(); | 1052 | hwa742.int_ctrl->cleanup(); |
| 1058 | if (hwa742.power_down != NULL) | 1053 | clk_disable(hwa742.sys_ck); |
| 1059 | hwa742.power_down(hwa742.fbdev->dev); | ||
| 1060 | } | 1054 | } |
| 1061 | 1055 | ||
| 1062 | struct lcd_ctrl hwa742_ctrl = { | 1056 | struct lcd_ctrl hwa742_ctrl = { |
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c new file mode 100644 index 000000000000..84d8327e47db --- /dev/null +++ b/drivers/video/pxa168fb.c | |||
| @@ -0,0 +1,803 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/video/pxa168fb.c -- Marvell PXA168 LCD Controller | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Marvell International Ltd. | ||
| 5 | * All rights reserved. | ||
| 6 | * | ||
| 7 | * 2009-02-16 adapted from original version for PXA168/910 | ||
| 8 | * Jun Nie <njun@marvell.com> | ||
| 9 | * | ||
| 10 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 11 | * License. See the file COPYING in the main directory of this archive for | ||
| 12 | * more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/sched.h> | ||
| 18 | #include <linux/string.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/fb.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/ioport.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | #include <linux/dma-mapping.h> | ||
| 27 | #include <linux/clk.h> | ||
| 28 | #include <linux/err.h> | ||
| 29 | #include <linux/uaccess.h> | ||
| 30 | #include <video/pxa168fb.h> | ||
| 31 | |||
| 32 | #include "pxa168fb.h" | ||
| 33 | |||
| 34 | #define DEFAULT_REFRESH 60 /* Hz */ | ||
| 35 | |||
| 36 | static int determine_best_pix_fmt(struct fb_var_screeninfo *var) | ||
| 37 | { | ||
| 38 | /* | ||
| 39 | * Pseudocolor mode? | ||
| 40 | */ | ||
| 41 | if (var->bits_per_pixel == 8) | ||
| 42 | return PIX_FMT_PSEUDOCOLOR; | ||
| 43 | |||
| 44 | /* | ||
| 45 | * Check for 565/1555. | ||
| 46 | */ | ||
| 47 | if (var->bits_per_pixel == 16 && var->red.length <= 5 && | ||
| 48 | var->green.length <= 6 && var->blue.length <= 5) { | ||
| 49 | if (var->transp.length == 0) { | ||
| 50 | if (var->red.offset >= var->blue.offset) | ||
| 51 | return PIX_FMT_RGB565; | ||
| 52 | else | ||
| 53 | return PIX_FMT_BGR565; | ||
| 54 | } | ||
| 55 | |||
| 56 | if (var->transp.length == 1 && var->green.length <= 5) { | ||
| 57 | if (var->red.offset >= var->blue.offset) | ||
| 58 | return PIX_FMT_RGB1555; | ||
| 59 | else | ||
| 60 | return PIX_FMT_BGR1555; | ||
| 61 | } | ||
| 62 | |||
| 63 | /* fall through */ | ||
| 64 | } | ||
| 65 | |||
| 66 | /* | ||
| 67 | * Check for 888/A888. | ||
| 68 | */ | ||
| 69 | if (var->bits_per_pixel <= 32 && var->red.length <= 8 && | ||
| 70 | var->green.length <= 8 && var->blue.length <= 8) { | ||
| 71 | if (var->bits_per_pixel == 24 && var->transp.length == 0) { | ||
| 72 | if (var->red.offset >= var->blue.offset) | ||
| 73 | return PIX_FMT_RGB888PACK; | ||
| 74 | else | ||
| 75 | return PIX_FMT_BGR888PACK; | ||
| 76 | } | ||
| 77 | |||
| 78 | if (var->bits_per_pixel == 32 && var->transp.length == 8) { | ||
| 79 | if (var->red.offset >= var->blue.offset) | ||
| 80 | return PIX_FMT_RGBA888; | ||
| 81 | else | ||
| 82 | return PIX_FMT_BGRA888; | ||
| 83 | } else { | ||
| 84 | if (var->red.offset >= var->blue.offset) | ||
| 85 | return PIX_FMT_RGB888UNPACK; | ||
| 86 | else | ||
| 87 | return PIX_FMT_BGR888UNPACK; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* fall through */ | ||
| 91 | } | ||
| 92 | |||
| 93 | return -EINVAL; | ||
| 94 | } | ||
| 95 | |||
| 96 | static void set_pix_fmt(struct fb_var_screeninfo *var, int pix_fmt) | ||
| 97 | { | ||
| 98 | switch (pix_fmt) { | ||
| 99 | case PIX_FMT_RGB565: | ||
| 100 | var->bits_per_pixel = 16; | ||
| 101 | var->red.offset = 11; var->red.length = 5; | ||
| 102 | var->green.offset = 5; var->green.length = 6; | ||
| 103 | var->blue.offset = 0; var->blue.length = 5; | ||
| 104 | var->transp.offset = 0; var->transp.length = 0; | ||
| 105 | break; | ||
| 106 | case PIX_FMT_BGR565: | ||
| 107 | var->bits_per_pixel = 16; | ||
| 108 | var->red.offset = 0; var->red.length = 5; | ||
| 109 | var->green.offset = 5; var->green.length = 6; | ||
| 110 | var->blue.offset = 11; var->blue.length = 5; | ||
| 111 | var->transp.offset = 0; var->transp.length = 0; | ||
| 112 | break; | ||
| 113 | case PIX_FMT_RGB1555: | ||
| 114 | var->bits_per_pixel = 16; | ||
| 115 | var->red.offset = 10; var->red.length = 5; | ||
| 116 | var->green.offset = 5; var->green.length = 5; | ||
| 117 | var->blue.offset = 0; var->blue.length = 5; | ||
| 118 | var->transp.offset = 15; var->transp.length = 1; | ||
| 119 | break; | ||
| 120 | case PIX_FMT_BGR1555: | ||
| 121 | var->bits_per_pixel = 16; | ||
| 122 | var->red.offset = 0; var->red.length = 5; | ||
| 123 | var->green.offset = 5; var->green.length = 5; | ||
| 124 | var->blue.offset = 10; var->blue.length = 5; | ||
| 125 | var->transp.offset = 15; var->transp.length = 1; | ||
| 126 | break; | ||
| 127 | case PIX_FMT_RGB888PACK: | ||
| 128 | var->bits_per_pixel = 24; | ||
| 129 | var->red.offset = 16; var->red.length = 8; | ||
| 130 | var->green.offset = 8; var->green.length = 8; | ||
| 131 | var->blue.offset = 0; var->blue.length = 8; | ||
| 132 | var->transp.offset = 0; var->transp.length = 0; | ||
| 133 | break; | ||
| 134 | case PIX_FMT_BGR888PACK: | ||
| 135 | var->bits_per_pixel = 24; | ||
| 136 | var->red.offset = 0; var->red.length = 8; | ||
| 137 | var->green.offset = 8; var->green.length = 8; | ||
| 138 | var->blue.offset = 16; var->blue.length = 8; | ||
| 139 | var->transp.offset = 0; var->transp.length = 0; | ||
| 140 | break; | ||
| 141 | case PIX_FMT_RGBA888: | ||
| 142 | var->bits_per_pixel = 32; | ||
| 143 | var->red.offset = 16; var->red.length = 8; | ||
| 144 | var->green.offset = 8; var->green.length = 8; | ||
| 145 | var->blue.offset = 0; var->blue.length = 8; | ||
| 146 | var->transp.offset = 24; var->transp.length = 8; | ||
| 147 | break; | ||
| 148 | case PIX_FMT_BGRA888: | ||
| 149 | var->bits_per_pixel = 32; | ||
| 150 | var->red.offset = 0; var->red.length = 8; | ||
| 151 | var->green.offset = 8; var->green.length = 8; | ||
| 152 | var->blue.offset = 16; var->blue.length = 8; | ||
| 153 | var->transp.offset = 24; var->transp.length = 8; | ||
| 154 | break; | ||
| 155 | case PIX_FMT_PSEUDOCOLOR: | ||
| 156 | var->bits_per_pixel = 8; | ||
| 157 | var->red.offset = 0; var->red.length = 8; | ||
| 158 | var->green.offset = 0; var->green.length = 8; | ||
| 159 | var->blue.offset = 0; var->blue.length = 8; | ||
| 160 | var->transp.offset = 0; var->transp.length = 0; | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | static void set_mode(struct pxa168fb_info *fbi, struct fb_var_screeninfo *var, | ||
| 166 | struct fb_videomode *mode, int pix_fmt, int ystretch) | ||
| 167 | { | ||
| 168 | struct fb_info *info = fbi->info; | ||
| 169 | |||
| 170 | set_pix_fmt(var, pix_fmt); | ||
| 171 | |||
| 172 | var->xres = mode->xres; | ||
| 173 | var->yres = mode->yres; | ||
| 174 | var->xres_virtual = max(var->xres, var->xres_virtual); | ||
| 175 | if (ystretch) | ||
| 176 | var->yres_virtual = info->fix.smem_len / | ||
| 177 | (var->xres_virtual * (var->bits_per_pixel >> 3)); | ||
| 178 | else | ||
| 179 | var->yres_virtual = max(var->yres, var->yres_virtual); | ||
| 180 | var->grayscale = 0; | ||
| 181 | var->accel_flags = FB_ACCEL_NONE; | ||
| 182 | var->pixclock = mode->pixclock; | ||
| 183 | var->left_margin = mode->left_margin; | ||
| 184 | var->right_margin = mode->right_margin; | ||
| 185 | var->upper_margin = mode->upper_margin; | ||
| 186 | var->lower_margin = mode->lower_margin; | ||
| 187 | var->hsync_len = mode->hsync_len; | ||
| 188 | var->vsync_len = mode->vsync_len; | ||
| 189 | var->sync = mode->sync; | ||
| 190 | var->vmode = FB_VMODE_NONINTERLACED; | ||
| 191 | var->rotate = FB_ROTATE_UR; | ||
| 192 | } | ||
| 193 | |||
| 194 | static int pxa168fb_check_var(struct fb_var_screeninfo *var, | ||
| 195 | struct fb_info *info) | ||
| 196 | { | ||
| 197 | struct pxa168fb_info *fbi = info->par; | ||
| 198 | int pix_fmt; | ||
| 199 | |||
| 200 | /* | ||
| 201 | * Determine which pixel format we're going to use. | ||
| 202 | */ | ||
| 203 | pix_fmt = determine_best_pix_fmt(var); | ||
| 204 | if (pix_fmt < 0) | ||
| 205 | return pix_fmt; | ||
| 206 | set_pix_fmt(var, pix_fmt); | ||
| 207 | fbi->pix_fmt = pix_fmt; | ||
| 208 | |||
| 209 | /* | ||
| 210 | * Basic geometry sanity checks. | ||
| 211 | */ | ||
| 212 | if (var->xoffset + var->xres > var->xres_virtual) | ||
| 213 | return -EINVAL; | ||
| 214 | if (var->yoffset + var->yres > var->yres_virtual) | ||
| 215 | return -EINVAL; | ||
| 216 | if (var->xres + var->right_margin + | ||
| 217 | var->hsync_len + var->left_margin > 2048) | ||
| 218 | return -EINVAL; | ||
| 219 | if (var->yres + var->lower_margin + | ||
| 220 | var->vsync_len + var->upper_margin > 2048) | ||
| 221 | return -EINVAL; | ||
| 222 | |||
| 223 | /* | ||
| 224 | * Check size of framebuffer. | ||
| 225 | */ | ||
| 226 | if (var->xres_virtual * var->yres_virtual * | ||
| 227 | (var->bits_per_pixel >> 3) > info->fix.smem_len) | ||
| 228 | return -EINVAL; | ||
| 229 | |||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 233 | /* | ||
| 234 | * The hardware clock divider has an integer and a fractional | ||
| 235 | * stage: | ||
| 236 | * | ||
| 237 | * clk2 = clk_in / integer_divider | ||
| 238 | * clk_out = clk2 * (1 - (fractional_divider >> 12)) | ||
| 239 | * | ||
| 240 | * Calculate integer and fractional divider for given clk_in | ||
| 241 | * and clk_out. | ||
| 242 | */ | ||
| 243 | static void set_clock_divider(struct pxa168fb_info *fbi, | ||
| 244 | const struct fb_videomode *m) | ||
| 245 | { | ||
| 246 | int divider_int; | ||
| 247 | int needed_pixclk; | ||
| 248 | u64 div_result; | ||
| 249 | u32 x = 0; | ||
| 250 | |||
| 251 | /* | ||
| 252 | * Notice: The field pixclock is used by linux fb | ||
| 253 | * is in pixel second. E.g. struct fb_videomode & | ||
| 254 | * struct fb_var_screeninfo | ||
| 255 | */ | ||
| 256 | |||
| 257 | /* | ||
| 258 | * Check input values. | ||
| 259 | */ | ||
| 260 | if (!m || !m->pixclock || !m->refresh) { | ||
| 261 | dev_err(fbi->dev, "Input refresh or pixclock is wrong.\n"); | ||
| 262 | return; | ||
| 263 | } | ||
| 264 | |||
| 265 | /* | ||
| 266 | * Using PLL/AXI clock. | ||
| 267 | */ | ||
| 268 | x = 0x80000000; | ||
| 269 | |||
| 270 | /* | ||
| 271 | * Calc divider according to refresh rate. | ||
| 272 | */ | ||
| 273 | div_result = 1000000000000ll; | ||
| 274 | do_div(div_result, m->pixclock); | ||
| 275 | needed_pixclk = (u32)div_result; | ||
| 276 | |||
| 277 | divider_int = clk_get_rate(fbi->clk) / needed_pixclk; | ||
| 278 | |||
| 279 | /* check whether divisor is too small. */ | ||
| 280 | if (divider_int < 2) { | ||
| 281 | dev_warn(fbi->dev, "Warning: clock source is too slow." | ||
| 282 | "Try smaller resolution\n"); | ||
| 283 | divider_int = 2; | ||
| 284 | } | ||
| 285 | |||
| 286 | /* | ||
| 287 | * Set setting to reg. | ||
| 288 | */ | ||
| 289 | x |= divider_int; | ||
| 290 | writel(x, fbi->reg_base + LCD_CFG_SCLK_DIV); | ||
| 291 | } | ||
| 292 | |||
| 293 | static void set_dma_control0(struct pxa168fb_info *fbi) | ||
| 294 | { | ||
| 295 | u32 x; | ||
| 296 | |||
| 297 | /* | ||
| 298 | * Set bit to enable graphics DMA. | ||
| 299 | */ | ||
| 300 | x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0); | ||
| 301 | x |= fbi->active ? 0x00000100 : 0; | ||
| 302 | fbi->active = 0; | ||
| 303 | |||
| 304 | /* | ||
| 305 | * If we are in a pseudo-color mode, we need to enable | ||
| 306 | * palette lookup. | ||
| 307 | */ | ||
| 308 | if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR) | ||
| 309 | x |= 0x10000000; | ||
| 310 | |||
| 311 | /* | ||
| 312 | * Configure hardware pixel format. | ||
| 313 | */ | ||
| 314 | x &= ~(0xF << 16); | ||
| 315 | x |= (fbi->pix_fmt >> 1) << 16; | ||
| 316 | |||
| 317 | /* | ||
| 318 | * Check red and blue pixel swap. | ||
| 319 | * 1. source data swap | ||
| 320 | * 2. panel output data swap | ||
| 321 | */ | ||
| 322 | x &= ~(1 << 12); | ||
| 323 | x |= ((fbi->pix_fmt & 1) ^ (fbi->panel_rbswap)) << 12; | ||
| 324 | |||
| 325 | writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL0); | ||
| 326 | } | ||
| 327 | |||
| 328 | static void set_dma_control1(struct pxa168fb_info *fbi, int sync) | ||
| 329 | { | ||
| 330 | u32 x; | ||
| 331 | |||
| 332 | /* | ||
| 333 | * Configure default bits: vsync triggers DMA, gated clock | ||
| 334 | * enable, power save enable, configure alpha registers to | ||
| 335 | * display 100% graphics, and set pixel command. | ||
| 336 | */ | ||
| 337 | x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL1); | ||
| 338 | x |= 0x2032ff81; | ||
| 339 | |||
| 340 | /* | ||
| 341 | * We trigger DMA on the falling edge of vsync if vsync is | ||
| 342 | * active low, or on the rising edge if vsync is active high. | ||
| 343 | */ | ||
| 344 | if (!(sync & FB_SYNC_VERT_HIGH_ACT)) | ||
| 345 | x |= 0x08000000; | ||
| 346 | |||
| 347 | writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL1); | ||
| 348 | } | ||
| 349 | |||
| 350 | static void set_graphics_start(struct fb_info *info, int xoffset, int yoffset) | ||
| 351 | { | ||
| 352 | struct pxa168fb_info *fbi = info->par; | ||
| 353 | struct fb_var_screeninfo *var = &info->var; | ||
| 354 | int pixel_offset; | ||
| 355 | unsigned long addr; | ||
| 356 | |||
| 357 | pixel_offset = (yoffset * var->xres_virtual) + xoffset; | ||
| 358 | |||
| 359 | addr = fbi->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3)); | ||
| 360 | writel(addr, fbi->reg_base + LCD_CFG_GRA_START_ADDR0); | ||
| 361 | } | ||
| 362 | |||
| 363 | static void set_dumb_panel_control(struct fb_info *info) | ||
| 364 | { | ||
| 365 | struct pxa168fb_info *fbi = info->par; | ||
| 366 | struct pxa168fb_mach_info *mi = fbi->dev->platform_data; | ||
| 367 | u32 x; | ||
| 368 | |||
| 369 | /* | ||
| 370 | * Preserve enable flag. | ||
| 371 | */ | ||
| 372 | x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL) & 0x00000001; | ||
| 373 | |||
| 374 | x |= (fbi->is_blanked ? 0x7 : mi->dumb_mode) << 28; | ||
| 375 | x |= mi->gpio_output_data << 20; | ||
| 376 | x |= mi->gpio_output_mask << 12; | ||
| 377 | x |= mi->panel_rgb_reverse_lanes ? 0x00000080 : 0; | ||
| 378 | x |= mi->invert_composite_blank ? 0x00000040 : 0; | ||
| 379 | x |= (info->var.sync & FB_SYNC_COMP_HIGH_ACT) ? 0x00000020 : 0; | ||
| 380 | x |= mi->invert_pix_val_ena ? 0x00000010 : 0; | ||
| 381 | x |= (info->var.sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x00000008; | ||
| 382 | x |= (info->var.sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x00000004; | ||
| 383 | x |= mi->invert_pixclock ? 0x00000002 : 0; | ||
| 384 | |||
| 385 | writel(x, fbi->reg_base + LCD_SPU_DUMB_CTRL); | ||
| 386 | } | ||
| 387 | |||
| 388 | static void set_dumb_screen_dimensions(struct fb_info *info) | ||
| 389 | { | ||
| 390 | struct pxa168fb_info *fbi = info->par; | ||
| 391 | struct fb_var_screeninfo *v = &info->var; | ||
| 392 | int x; | ||
| 393 | int y; | ||
| 394 | |||
| 395 | x = v->xres + v->right_margin + v->hsync_len + v->left_margin; | ||
| 396 | y = v->yres + v->lower_margin + v->vsync_len + v->upper_margin; | ||
| 397 | |||
| 398 | writel((y << 16) | x, fbi->reg_base + LCD_SPUT_V_H_TOTAL); | ||
| 399 | } | ||
| 400 | |||
| 401 | static int pxa168fb_set_par(struct fb_info *info) | ||
| 402 | { | ||
| 403 | struct pxa168fb_info *fbi = info->par; | ||
| 404 | struct fb_var_screeninfo *var = &info->var; | ||
| 405 | struct fb_videomode mode; | ||
| 406 | u32 x; | ||
| 407 | struct pxa168fb_mach_info *mi; | ||
| 408 | |||
| 409 | mi = fbi->dev->platform_data; | ||
| 410 | |||
| 411 | /* | ||
| 412 | * Set additional mode info. | ||
| 413 | */ | ||
| 414 | if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR) | ||
| 415 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
| 416 | else | ||
| 417 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
| 418 | info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; | ||
| 419 | info->fix.ypanstep = var->yres; | ||
| 420 | |||
| 421 | /* | ||
| 422 | * Disable panel output while we setup the display. | ||
| 423 | */ | ||
| 424 | x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL); | ||
| 425 | writel(x & ~1, fbi->reg_base + LCD_SPU_DUMB_CTRL); | ||
| 426 | |||
| 427 | /* | ||
| 428 | * Configure global panel parameters. | ||
| 429 | */ | ||
| 430 | writel((var->yres << 16) | var->xres, | ||
| 431 | fbi->reg_base + LCD_SPU_V_H_ACTIVE); | ||
| 432 | |||
| 433 | /* | ||
| 434 | * convet var to video mode | ||
| 435 | */ | ||
| 436 | fb_var_to_videomode(&mode, &info->var); | ||
| 437 | |||
| 438 | /* Calculate clock divisor. */ | ||
| 439 | set_clock_divider(fbi, &mode); | ||
| 440 | |||
| 441 | /* Configure dma ctrl regs. */ | ||
| 442 | set_dma_control0(fbi); | ||
| 443 | set_dma_control1(fbi, info->var.sync); | ||
| 444 | |||
| 445 | /* | ||
| 446 | * Configure graphics DMA parameters. | ||
| 447 | */ | ||
| 448 | x = readl(fbi->reg_base + LCD_CFG_GRA_PITCH); | ||
| 449 | x = (x & ~0xFFFF) | ((var->xres_virtual * var->bits_per_pixel) >> 3); | ||
| 450 | writel(x, fbi->reg_base + LCD_CFG_GRA_PITCH); | ||
| 451 | writel((var->yres << 16) | var->xres, | ||
| 452 | fbi->reg_base + LCD_SPU_GRA_HPXL_VLN); | ||
| 453 | writel((var->yres << 16) | var->xres, | ||
| 454 | fbi->reg_base + LCD_SPU_GZM_HPXL_VLN); | ||
| 455 | |||
| 456 | /* | ||
| 457 | * Configure dumb panel ctrl regs & timings. | ||
| 458 | */ | ||
| 459 | set_dumb_panel_control(info); | ||
| 460 | set_dumb_screen_dimensions(info); | ||
| 461 | |||
| 462 | writel((var->left_margin << 16) | var->right_margin, | ||
| 463 | fbi->reg_base + LCD_SPU_H_PORCH); | ||
| 464 | writel((var->upper_margin << 16) | var->lower_margin, | ||
| 465 | fbi->reg_base + LCD_SPU_V_PORCH); | ||
| 466 | |||
| 467 | /* | ||
| 468 | * Re-enable panel output. | ||
| 469 | */ | ||
| 470 | x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL); | ||
| 471 | writel(x | 1, fbi->reg_base + LCD_SPU_DUMB_CTRL); | ||
| 472 | |||
| 473 | return 0; | ||
| 474 | } | ||
| 475 | |||
| 476 | static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf) | ||
| 477 | { | ||
| 478 | return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset; | ||
| 479 | } | ||
| 480 | |||
| 481 | static u32 to_rgb(u16 red, u16 green, u16 blue) | ||
| 482 | { | ||
| 483 | red >>= 8; | ||
| 484 | green >>= 8; | ||
| 485 | blue >>= 8; | ||
| 486 | |||
| 487 | return (red << 16) | (green << 8) | blue; | ||
| 488 | } | ||
| 489 | |||
| 490 | static int | ||
| 491 | pxa168fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, | ||
| 492 | unsigned int blue, unsigned int trans, struct fb_info *info) | ||
| 493 | { | ||
| 494 | struct pxa168fb_info *fbi = info->par; | ||
| 495 | u32 val; | ||
| 496 | |||
| 497 | if (info->var.grayscale) | ||
| 498 | red = green = blue = (19595 * red + 38470 * green + | ||
| 499 | 7471 * blue) >> 16; | ||
| 500 | |||
| 501 | if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) { | ||
| 502 | val = chan_to_field(red, &info->var.red); | ||
| 503 | val |= chan_to_field(green, &info->var.green); | ||
| 504 | val |= chan_to_field(blue , &info->var.blue); | ||
| 505 | fbi->pseudo_palette[regno] = val; | ||
| 506 | } | ||
| 507 | |||
| 508 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) { | ||
| 509 | val = to_rgb(red, green, blue); | ||
| 510 | writel(val, fbi->reg_base + LCD_SPU_SRAM_WRDAT); | ||
| 511 | writel(0x8300 | regno, fbi->reg_base + LCD_SPU_SRAM_CTRL); | ||
| 512 | } | ||
| 513 | |||
| 514 | return 0; | ||
| 515 | } | ||
| 516 | |||
| 517 | static int pxa168fb_blank(int blank, struct fb_info *info) | ||
| 518 | { | ||
| 519 | struct pxa168fb_info *fbi = info->par; | ||
| 520 | |||
| 521 | fbi->is_blanked = (blank == FB_BLANK_UNBLANK) ? 0 : 1; | ||
| 522 | set_dumb_panel_control(info); | ||
| 523 | |||
| 524 | return 0; | ||
| 525 | } | ||
| 526 | |||
| 527 | static int pxa168fb_pan_display(struct fb_var_screeninfo *var, | ||
| 528 | struct fb_info *info) | ||
| 529 | { | ||
| 530 | set_graphics_start(info, var->xoffset, var->yoffset); | ||
| 531 | |||
| 532 | return 0; | ||
| 533 | } | ||
| 534 | |||
| 535 | static irqreturn_t pxa168fb_handle_irq(int irq, void *dev_id) | ||
| 536 | { | ||
| 537 | struct pxa168fb_info *fbi = dev_id; | ||
| 538 | u32 isr = readl(fbi->reg_base + SPU_IRQ_ISR); | ||
| 539 | |||
| 540 | if ((isr & GRA_FRAME_IRQ0_ENA_MASK)) { | ||
| 541 | |||
| 542 | writel(isr & (~GRA_FRAME_IRQ0_ENA_MASK), | ||
| 543 | fbi->reg_base + SPU_IRQ_ISR); | ||
| 544 | |||
| 545 | return IRQ_HANDLED; | ||
| 546 | } | ||
| 547 | return IRQ_NONE; | ||
| 548 | } | ||
| 549 | |||
| 550 | static struct fb_ops pxa168fb_ops = { | ||
| 551 | .owner = THIS_MODULE, | ||
| 552 | .fb_check_var = pxa168fb_check_var, | ||
| 553 | .fb_set_par = pxa168fb_set_par, | ||
| 554 | .fb_setcolreg = pxa168fb_setcolreg, | ||
| 555 | .fb_blank = pxa168fb_blank, | ||
| 556 | .fb_pan_display = pxa168fb_pan_display, | ||
| 557 | .fb_fillrect = cfb_fillrect, | ||
| 558 | .fb_copyarea = cfb_copyarea, | ||
| 559 | .fb_imageblit = cfb_imageblit, | ||
| 560 | }; | ||
| 561 | |||
| 562 | static int __init pxa168fb_init_mode(struct fb_info *info, | ||
| 563 | struct pxa168fb_mach_info *mi) | ||
| 564 | { | ||
| 565 | struct pxa168fb_info *fbi = info->par; | ||
| 566 | struct fb_var_screeninfo *var = &info->var; | ||
| 567 | int ret = 0; | ||
| 568 | u32 total_w, total_h, refresh; | ||
| 569 | u64 div_result; | ||
| 570 | const struct fb_videomode *m; | ||
| 571 | |||
| 572 | /* | ||
| 573 | * Set default value | ||
| 574 | */ | ||
| 575 | refresh = DEFAULT_REFRESH; | ||
| 576 | |||
| 577 | /* try to find best video mode. */ | ||
| 578 | m = fb_find_best_mode(&info->var, &info->modelist); | ||
| 579 | if (m) | ||
| 580 | fb_videomode_to_var(&info->var, m); | ||
| 581 | |||
| 582 | /* Init settings. */ | ||
| 583 | var->xres_virtual = var->xres; | ||
| 584 | var->yres_virtual = info->fix.smem_len / | ||
| 585 | (var->xres_virtual * (var->bits_per_pixel >> 3)); | ||
| 586 | dev_dbg(fbi->dev, "pxa168fb: find best mode: res = %dx%d\n", | ||
| 587 | var->xres, var->yres); | ||
| 588 | |||
| 589 | /* correct pixclock. */ | ||
| 590 | total_w = var->xres + var->left_margin + var->right_margin + | ||
| 591 | var->hsync_len; | ||
| 592 | total_h = var->yres + var->upper_margin + var->lower_margin + | ||
| 593 | var->vsync_len; | ||
| 594 | |||
| 595 | div_result = 1000000000000ll; | ||
| 596 | do_div(div_result, total_w * total_h * refresh); | ||
| 597 | var->pixclock = (u32)div_result; | ||
| 598 | |||
| 599 | return ret; | ||
| 600 | } | ||
| 601 | |||
| 602 | static int __init pxa168fb_probe(struct platform_device *pdev) | ||
| 603 | { | ||
| 604 | struct pxa168fb_mach_info *mi; | ||
| 605 | struct fb_info *info = 0; | ||
| 606 | struct pxa168fb_info *fbi = 0; | ||
| 607 | struct resource *res; | ||
| 608 | struct clk *clk; | ||
| 609 | int irq, ret; | ||
| 610 | |||
| 611 | mi = pdev->dev.platform_data; | ||
| 612 | if (mi == NULL) { | ||
| 613 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
| 614 | return -EINVAL; | ||
| 615 | } | ||
| 616 | |||
| 617 | clk = clk_get(&pdev->dev, "LCDCLK"); | ||
| 618 | if (IS_ERR(clk)) { | ||
| 619 | dev_err(&pdev->dev, "unable to get LCDCLK"); | ||
| 620 | return PTR_ERR(clk); | ||
| 621 | } | ||
| 622 | |||
| 623 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 624 | if (res == NULL) { | ||
| 625 | dev_err(&pdev->dev, "no IO memory defined\n"); | ||
| 626 | return -ENOENT; | ||
| 627 | } | ||
| 628 | |||
| 629 | irq = platform_get_irq(pdev, 0); | ||
| 630 | if (irq < 0) { | ||
| 631 | dev_err(&pdev->dev, "no IRQ defined\n"); | ||
| 632 | return -ENOENT; | ||
| 633 | } | ||
| 634 | |||
| 635 | info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev); | ||
| 636 | if (info == NULL) { | ||
| 637 | clk_put(clk); | ||
| 638 | return -ENOMEM; | ||
| 639 | } | ||
| 640 | |||
| 641 | /* Initialize private data */ | ||
| 642 | fbi = info->par; | ||
| 643 | fbi->info = info; | ||
| 644 | fbi->clk = clk; | ||
| 645 | fbi->dev = info->dev = &pdev->dev; | ||
| 646 | fbi->panel_rbswap = mi->panel_rbswap; | ||
| 647 | fbi->is_blanked = 0; | ||
| 648 | fbi->active = mi->active; | ||
| 649 | |||
| 650 | /* | ||
| 651 | * Initialise static fb parameters. | ||
| 652 | */ | ||
| 653 | info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | | ||
| 654 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; | ||
| 655 | info->node = -1; | ||
| 656 | strlcpy(info->fix.id, mi->id, 16); | ||
| 657 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
| 658 | info->fix.type_aux = 0; | ||
| 659 | info->fix.xpanstep = 0; | ||
| 660 | info->fix.ypanstep = 0; | ||
| 661 | info->fix.ywrapstep = 0; | ||
| 662 | info->fix.mmio_start = res->start; | ||
| 663 | info->fix.mmio_len = res->end - res->start + 1; | ||
| 664 | info->fix.accel = FB_ACCEL_NONE; | ||
| 665 | info->fbops = &pxa168fb_ops; | ||
| 666 | info->pseudo_palette = fbi->pseudo_palette; | ||
| 667 | |||
| 668 | /* | ||
| 669 | * Map LCD controller registers. | ||
| 670 | */ | ||
| 671 | fbi->reg_base = ioremap_nocache(res->start, res->end - res->start); | ||
| 672 | if (fbi->reg_base == NULL) { | ||
| 673 | ret = -ENOMEM; | ||
| 674 | goto failed; | ||
| 675 | } | ||
| 676 | |||
| 677 | /* | ||
| 678 | * Allocate framebuffer memory. | ||
| 679 | */ | ||
| 680 | info->fix.smem_len = PAGE_ALIGN(DEFAULT_FB_SIZE); | ||
| 681 | |||
| 682 | info->screen_base = dma_alloc_writecombine(fbi->dev, info->fix.smem_len, | ||
| 683 | &fbi->fb_start_dma, GFP_KERNEL); | ||
| 684 | if (info->screen_base == NULL) { | ||
| 685 | ret = -ENOMEM; | ||
| 686 | goto failed; | ||
| 687 | } | ||
| 688 | |||
| 689 | info->fix.smem_start = (unsigned long)fbi->fb_start_dma; | ||
| 690 | |||
| 691 | /* | ||
| 692 | * Set video mode according to platform data. | ||
| 693 | */ | ||
| 694 | set_mode(fbi, &info->var, mi->modes, mi->pix_fmt, 1); | ||
| 695 | |||
| 696 | fb_videomode_to_modelist(mi->modes, mi->num_modes, &info->modelist); | ||
| 697 | |||
| 698 | /* | ||
| 699 | * init video mode data. | ||
| 700 | */ | ||
| 701 | pxa168fb_init_mode(info, mi); | ||
| 702 | |||
| 703 | ret = pxa168fb_check_var(&info->var, info); | ||
| 704 | if (ret) | ||
| 705 | goto failed_free_fbmem; | ||
| 706 | |||
| 707 | /* | ||
| 708 | * Fill in sane defaults. | ||
| 709 | */ | ||
| 710 | ret = pxa168fb_check_var(&info->var, info); | ||
| 711 | if (ret) | ||
| 712 | goto failed; | ||
| 713 | |||
| 714 | /* | ||
| 715 | * enable controller clock | ||
| 716 | */ | ||
| 717 | clk_enable(fbi->clk); | ||
| 718 | |||
| 719 | pxa168fb_set_par(info); | ||
| 720 | |||
| 721 | /* | ||
| 722 | * Configure default register values. | ||
| 723 | */ | ||
| 724 | writel(0, fbi->reg_base + LCD_SPU_BLANKCOLOR); | ||
| 725 | writel(mi->io_pin_allocation_mode, fbi->reg_base + SPU_IOPAD_CONTROL); | ||
| 726 | writel(0, fbi->reg_base + LCD_CFG_GRA_START_ADDR1); | ||
| 727 | writel(0, fbi->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN); | ||
| 728 | writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0); | ||
| 729 | writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1), | ||
| 730 | fbi->reg_base + LCD_SPU_SRAM_PARA1); | ||
| 731 | |||
| 732 | /* | ||
| 733 | * Allocate color map. | ||
| 734 | */ | ||
| 735 | if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { | ||
| 736 | ret = -ENOMEM; | ||
| 737 | goto failed_free_clk; | ||
| 738 | } | ||
| 739 | |||
| 740 | /* | ||
| 741 | * Register irq handler. | ||
| 742 | */ | ||
| 743 | ret = request_irq(irq, pxa168fb_handle_irq, IRQF_SHARED, | ||
| 744 | info->fix.id, fbi); | ||
| 745 | if (ret < 0) { | ||
| 746 | dev_err(&pdev->dev, "unable to request IRQ\n"); | ||
| 747 | ret = -ENXIO; | ||
| 748 | goto failed_free_cmap; | ||
| 749 | } | ||
| 750 | |||
| 751 | /* | ||
| 752 | * Enable GFX interrupt | ||
| 753 | */ | ||
| 754 | writel(GRA_FRAME_IRQ0_ENA(0x1), fbi->reg_base + SPU_IRQ_ENA); | ||
| 755 | |||
| 756 | /* | ||
| 757 | * Register framebuffer. | ||
| 758 | */ | ||
| 759 | ret = register_framebuffer(info); | ||
| 760 | if (ret < 0) { | ||
| 761 | dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret); | ||
| 762 | ret = -ENXIO; | ||
| 763 | goto failed_free_irq; | ||
| 764 | } | ||
| 765 | |||
| 766 | platform_set_drvdata(pdev, fbi); | ||
| 767 | return 0; | ||
| 768 | |||
| 769 | failed_free_irq: | ||
| 770 | free_irq(irq, fbi); | ||
| 771 | failed_free_cmap: | ||
| 772 | fb_dealloc_cmap(&info->cmap); | ||
| 773 | failed_free_clk: | ||
| 774 | clk_disable(fbi->clk); | ||
| 775 | failed_free_fbmem: | ||
| 776 | dma_free_coherent(fbi->dev, info->fix.smem_len, | ||
| 777 | info->screen_base, fbi->fb_start_dma); | ||
| 778 | failed: | ||
| 779 | kfree(info); | ||
| 780 | clk_put(clk); | ||
| 781 | |||
| 782 | dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret); | ||
| 783 | return ret; | ||
| 784 | } | ||
| 785 | |||
| 786 | static struct platform_driver pxa168fb_driver = { | ||
| 787 | .driver = { | ||
| 788 | .name = "pxa168-fb", | ||
| 789 | .owner = THIS_MODULE, | ||
| 790 | }, | ||
| 791 | .probe = pxa168fb_probe, | ||
| 792 | }; | ||
| 793 | |||
| 794 | static int __devinit pxa168fb_init(void) | ||
| 795 | { | ||
| 796 | return platform_driver_register(&pxa168fb_driver); | ||
| 797 | } | ||
| 798 | module_init(pxa168fb_init); | ||
| 799 | |||
| 800 | MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> " | ||
| 801 | "Green Wan <gwan@marvell.com>"); | ||
| 802 | MODULE_DESCRIPTION("Framebuffer driver for PXA168/910"); | ||
| 803 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h new file mode 100644 index 000000000000..eee09279c524 --- /dev/null +++ b/drivers/video/pxa168fb.h | |||
| @@ -0,0 +1,558 @@ | |||
| 1 | #ifndef __PXA168FB_H__ | ||
| 2 | #define __PXA168FB_H__ | ||
| 3 | |||
| 4 | /* ------------< LCD register >------------ */ | ||
| 5 | /* Video Frame 0&1 start address registers */ | ||
| 6 | #define LCD_SPU_DMA_START_ADDR_Y0 0x00C0 | ||
| 7 | #define LCD_SPU_DMA_START_ADDR_U0 0x00C4 | ||
| 8 | #define LCD_SPU_DMA_START_ADDR_V0 0x00C8 | ||
| 9 | #define LCD_CFG_DMA_START_ADDR_0 0x00CC /* Cmd address */ | ||
| 10 | #define LCD_SPU_DMA_START_ADDR_Y1 0x00D0 | ||
| 11 | #define LCD_SPU_DMA_START_ADDR_U1 0x00D4 | ||
| 12 | #define LCD_SPU_DMA_START_ADDR_V1 0x00D8 | ||
| 13 | #define LCD_CFG_DMA_START_ADDR_1 0x00DC /* Cmd address */ | ||
| 14 | |||
| 15 | /* YC & UV Pitch */ | ||
| 16 | #define LCD_SPU_DMA_PITCH_YC 0x00E0 | ||
| 17 | #define SPU_DMA_PITCH_C(c) ((c) << 16) | ||
| 18 | #define SPU_DMA_PITCH_Y(y) (y) | ||
| 19 | #define LCD_SPU_DMA_PITCH_UV 0x00E4 | ||
| 20 | #define SPU_DMA_PITCH_V(v) ((v) << 16) | ||
| 21 | #define SPU_DMA_PITCH_U(u) (u) | ||
| 22 | |||
| 23 | /* Video Starting Point on Screen Register */ | ||
| 24 | #define LCD_SPUT_DMA_OVSA_HPXL_VLN 0x00E8 | ||
| 25 | #define CFG_DMA_OVSA_VLN(y) ((y) << 16) /* 0~0xfff */ | ||
| 26 | #define CFG_DMA_OVSA_HPXL(x) (x) /* 0~0xfff */ | ||
| 27 | |||
| 28 | /* Video Size Register */ | ||
| 29 | #define LCD_SPU_DMA_HPXL_VLN 0x00EC | ||
| 30 | #define CFG_DMA_VLN(y) ((y) << 16) | ||
| 31 | #define CFG_DMA_HPXL(x) (x) | ||
| 32 | |||
| 33 | /* Video Size After zooming Register */ | ||
| 34 | #define LCD_SPU_DZM_HPXL_VLN 0x00F0 | ||
| 35 | #define CFG_DZM_VLN(y) ((y) << 16) | ||
| 36 | #define CFG_DZM_HPXL(x) (x) | ||
| 37 | |||
| 38 | /* Graphic Frame 0&1 Starting Address Register */ | ||
| 39 | #define LCD_CFG_GRA_START_ADDR0 0x00F4 | ||
| 40 | #define LCD_CFG_GRA_START_ADDR1 0x00F8 | ||
| 41 | |||
| 42 | /* Graphic Frame Pitch */ | ||
| 43 | #define LCD_CFG_GRA_PITCH 0x00FC | ||
| 44 | |||
| 45 | /* Graphic Starting Point on Screen Register */ | ||
| 46 | #define LCD_SPU_GRA_OVSA_HPXL_VLN 0x0100 | ||
| 47 | #define CFG_GRA_OVSA_VLN(y) ((y) << 16) | ||
| 48 | #define CFG_GRA_OVSA_HPXL(x) (x) | ||
| 49 | |||
| 50 | /* Graphic Size Register */ | ||
| 51 | #define LCD_SPU_GRA_HPXL_VLN 0x0104 | ||
| 52 | #define CFG_GRA_VLN(y) ((y) << 16) | ||
| 53 | #define CFG_GRA_HPXL(x) (x) | ||
| 54 | |||
| 55 | /* Graphic Size after Zooming Register */ | ||
| 56 | #define LCD_SPU_GZM_HPXL_VLN 0x0108 | ||
| 57 | #define CFG_GZM_VLN(y) ((y) << 16) | ||
| 58 | #define CFG_GZM_HPXL(x) (x) | ||
| 59 | |||
| 60 | /* HW Cursor Starting Point on Screen Register */ | ||
| 61 | #define LCD_SPU_HWC_OVSA_HPXL_VLN 0x010C | ||
| 62 | #define CFG_HWC_OVSA_VLN(y) ((y) << 16) | ||
| 63 | #define CFG_HWC_OVSA_HPXL(x) (x) | ||
| 64 | |||
| 65 | /* HW Cursor Size */ | ||
| 66 | #define LCD_SPU_HWC_HPXL_VLN 0x0110 | ||
| 67 | #define CFG_HWC_VLN(y) ((y) << 16) | ||
| 68 | #define CFG_HWC_HPXL(x) (x) | ||
| 69 | |||
| 70 | /* Total Screen Size Register */ | ||
| 71 | #define LCD_SPUT_V_H_TOTAL 0x0114 | ||
| 72 | #define CFG_V_TOTAL(y) ((y) << 16) | ||
| 73 | #define CFG_H_TOTAL(x) (x) | ||
| 74 | |||
| 75 | /* Total Screen Active Size Register */ | ||
| 76 | #define LCD_SPU_V_H_ACTIVE 0x0118 | ||
| 77 | #define CFG_V_ACTIVE(y) ((y) << 16) | ||
| 78 | #define CFG_H_ACTIVE(x) (x) | ||
| 79 | |||
| 80 | /* Screen H&V Porch Register */ | ||
| 81 | #define LCD_SPU_H_PORCH 0x011C | ||
| 82 | #define CFG_H_BACK_PORCH(b) ((b) << 16) | ||
| 83 | #define CFG_H_FRONT_PORCH(f) (f) | ||
| 84 | #define LCD_SPU_V_PORCH 0x0120 | ||
| 85 | #define CFG_V_BACK_PORCH(b) ((b) << 16) | ||
| 86 | #define CFG_V_FRONT_PORCH(f) (f) | ||
| 87 | |||
| 88 | /* Screen Blank Color Register */ | ||
| 89 | #define LCD_SPU_BLANKCOLOR 0x0124 | ||
| 90 | #define CFG_BLANKCOLOR_MASK 0x00FFFFFF | ||
| 91 | #define CFG_BLANKCOLOR_R_MASK 0x000000FF | ||
| 92 | #define CFG_BLANKCOLOR_G_MASK 0x0000FF00 | ||
| 93 | #define CFG_BLANKCOLOR_B_MASK 0x00FF0000 | ||
| 94 | |||
| 95 | /* HW Cursor Color 1&2 Register */ | ||
| 96 | #define LCD_SPU_ALPHA_COLOR1 0x0128 | ||
| 97 | #define CFG_HWC_COLOR1 0x00FFFFFF | ||
| 98 | #define CFG_HWC_COLOR1_R(red) ((red) << 16) | ||
| 99 | #define CFG_HWC_COLOR1_G(green) ((green) << 8) | ||
| 100 | #define CFG_HWC_COLOR1_B(blue) (blue) | ||
| 101 | #define CFG_HWC_COLOR1_R_MASK 0x000000FF | ||
| 102 | #define CFG_HWC_COLOR1_G_MASK 0x0000FF00 | ||
| 103 | #define CFG_HWC_COLOR1_B_MASK 0x00FF0000 | ||
| 104 | #define LCD_SPU_ALPHA_COLOR2 0x012C | ||
| 105 | #define CFG_HWC_COLOR2 0x00FFFFFF | ||
| 106 | #define CFG_HWC_COLOR2_R_MASK 0x000000FF | ||
| 107 | #define CFG_HWC_COLOR2_G_MASK 0x0000FF00 | ||
| 108 | #define CFG_HWC_COLOR2_B_MASK 0x00FF0000 | ||
| 109 | |||
| 110 | /* Video YUV Color Key Control */ | ||
| 111 | #define LCD_SPU_COLORKEY_Y 0x0130 | ||
| 112 | #define CFG_CKEY_Y2(y2) ((y2) << 24) | ||
| 113 | #define CFG_CKEY_Y2_MASK 0xFF000000 | ||
| 114 | #define CFG_CKEY_Y1(y1) ((y1) << 16) | ||
| 115 | #define CFG_CKEY_Y1_MASK 0x00FF0000 | ||
| 116 | #define CFG_CKEY_Y(y) ((y) << 8) | ||
| 117 | #define CFG_CKEY_Y_MASK 0x0000FF00 | ||
| 118 | #define CFG_ALPHA_Y(y) (y) | ||
| 119 | #define CFG_ALPHA_Y_MASK 0x000000FF | ||
| 120 | #define LCD_SPU_COLORKEY_U 0x0134 | ||
| 121 | #define CFG_CKEY_U2(u2) ((u2) << 24) | ||
| 122 | #define CFG_CKEY_U2_MASK 0xFF000000 | ||
| 123 | #define CFG_CKEY_U1(u1) ((u1) << 16) | ||
| 124 | #define CFG_CKEY_U1_MASK 0x00FF0000 | ||
| 125 | #define CFG_CKEY_U(u) ((u) << 8) | ||
| 126 | #define CFG_CKEY_U_MASK 0x0000FF00 | ||
| 127 | #define CFG_ALPHA_U(u) (u) | ||
| 128 | #define CFG_ALPHA_U_MASK 0x000000FF | ||
| 129 | #define LCD_SPU_COLORKEY_V 0x0138 | ||
| 130 | #define CFG_CKEY_V2(v2) ((v2) << 24) | ||
| 131 | #define CFG_CKEY_V2_MASK 0xFF000000 | ||
| 132 | #define CFG_CKEY_V1(v1) ((v1) << 16) | ||
| 133 | #define CFG_CKEY_V1_MASK 0x00FF0000 | ||
| 134 | #define CFG_CKEY_V(v) ((v) << 8) | ||
| 135 | #define CFG_CKEY_V_MASK 0x0000FF00 | ||
| 136 | #define CFG_ALPHA_V(v) (v) | ||
| 137 | #define CFG_ALPHA_V_MASK 0x000000FF | ||
| 138 | |||
| 139 | /* SPI Read Data Register */ | ||
| 140 | #define LCD_SPU_SPI_RXDATA 0x0140 | ||
| 141 | |||
| 142 | /* Smart Panel Read Data Register */ | ||
| 143 | #define LCD_SPU_ISA_RSDATA 0x0144 | ||
| 144 | #define ISA_RXDATA_16BIT_1_DATA_MASK 0x000000FF | ||
| 145 | #define ISA_RXDATA_16BIT_2_DATA_MASK 0x0000FF00 | ||
| 146 | #define ISA_RXDATA_16BIT_3_DATA_MASK 0x00FF0000 | ||
| 147 | #define ISA_RXDATA_16BIT_4_DATA_MASK 0xFF000000 | ||
| 148 | #define ISA_RXDATA_32BIT_1_DATA_MASK 0x00FFFFFF | ||
| 149 | |||
| 150 | /* HWC SRAM Read Data Register */ | ||
| 151 | #define LCD_SPU_HWC_RDDAT 0x0158 | ||
| 152 | |||
| 153 | /* Gamma Table SRAM Read Data Register */ | ||
| 154 | #define LCD_SPU_GAMMA_RDDAT 0x015c | ||
| 155 | #define CFG_GAMMA_RDDAT_MASK 0x000000FF | ||
| 156 | |||
| 157 | /* Palette Table SRAM Read Data Register */ | ||
| 158 | #define LCD_SPU_PALETTE_RDDAT 0x0160 | ||
| 159 | #define CFG_PALETTE_RDDAT_MASK 0x00FFFFFF | ||
| 160 | |||
| 161 | /* I/O Pads Input Read Only Register */ | ||
| 162 | #define LCD_SPU_IOPAD_IN 0x0178 | ||
| 163 | #define CFG_IOPAD_IN_MASK 0x0FFFFFFF | ||
| 164 | |||
| 165 | /* Reserved Read Only Registers */ | ||
| 166 | #define LCD_CFG_RDREG5F 0x017C | ||
| 167 | #define IRE_FRAME_CNT_MASK 0x000000C0 | ||
| 168 | #define IPE_FRAME_CNT_MASK 0x00000030 | ||
| 169 | #define GRA_FRAME_CNT_MASK 0x0000000C /* Graphic */ | ||
| 170 | #define DMA_FRAME_CNT_MASK 0x00000003 /* Video */ | ||
| 171 | |||
| 172 | /* SPI Control Register. */ | ||
| 173 | #define LCD_SPU_SPI_CTRL 0x0180 | ||
| 174 | #define CFG_SCLKCNT(div) ((div) << 24) /* 0xFF~0x2 */ | ||
| 175 | #define CFG_SCLKCNT_MASK 0xFF000000 | ||
| 176 | #define CFG_RXBITS(rx) ((rx) << 16) /* 0x1F~0x1 */ | ||
| 177 | #define CFG_RXBITS_MASK 0x00FF0000 | ||
| 178 | #define CFG_TXBITS(tx) ((tx) << 8) /* 0x1F~0x1 */ | ||
| 179 | #define CFG_TXBITS_MASK 0x0000FF00 | ||
| 180 | #define CFG_CLKINV(clk) ((clk) << 7) | ||
| 181 | #define CFG_CLKINV_MASK 0x00000080 | ||
| 182 | #define CFG_KEEPXFER(transfer) ((transfer) << 6) | ||
| 183 | #define CFG_KEEPXFER_MASK 0x00000040 | ||
| 184 | #define CFG_RXBITSTO0(rx) ((rx) << 5) | ||
| 185 | #define CFG_RXBITSTO0_MASK 0x00000020 | ||
| 186 | #define CFG_TXBITSTO0(tx) ((tx) << 4) | ||
| 187 | #define CFG_TXBITSTO0_MASK 0x00000010 | ||
| 188 | #define CFG_SPI_ENA(spi) ((spi) << 3) | ||
| 189 | #define CFG_SPI_ENA_MASK 0x00000008 | ||
| 190 | #define CFG_SPI_SEL(spi) ((spi) << 2) | ||
| 191 | #define CFG_SPI_SEL_MASK 0x00000004 | ||
| 192 | #define CFG_SPI_3W4WB(wire) ((wire) << 1) | ||
| 193 | #define CFG_SPI_3W4WB_MASK 0x00000002 | ||
| 194 | #define CFG_SPI_START(start) (start) | ||
| 195 | #define CFG_SPI_START_MASK 0x00000001 | ||
| 196 | |||
| 197 | /* SPI Tx Data Register */ | ||
| 198 | #define LCD_SPU_SPI_TXDATA 0x0184 | ||
| 199 | |||
| 200 | /* | ||
| 201 | 1. Smart Pannel 8-bit Bus Control Register. | ||
| 202 | 2. AHB Slave Path Data Port Register | ||
| 203 | */ | ||
| 204 | #define LCD_SPU_SMPN_CTRL 0x0188 | ||
| 205 | |||
| 206 | /* DMA Control 0 Register */ | ||
| 207 | #define LCD_SPU_DMA_CTRL0 0x0190 | ||
| 208 | #define CFG_NOBLENDING(nb) ((nb) << 31) | ||
| 209 | #define CFG_NOBLENDING_MASK 0x80000000 | ||
| 210 | #define CFG_GAMMA_ENA(gn) ((gn) << 30) | ||
| 211 | #define CFG_GAMMA_ENA_MASK 0x40000000 | ||
| 212 | #define CFG_CBSH_ENA(cn) ((cn) << 29) | ||
| 213 | #define CFG_CBSH_ENA_MASK 0x20000000 | ||
| 214 | #define CFG_PALETTE_ENA(pn) ((pn) << 28) | ||
| 215 | #define CFG_PALETTE_ENA_MASK 0x10000000 | ||
| 216 | #define CFG_ARBFAST_ENA(an) ((an) << 27) | ||
| 217 | #define CFG_ARBFAST_ENA_MASK 0x08000000 | ||
| 218 | #define CFG_HWC_1BITMOD(mode) ((mode) << 26) | ||
| 219 | #define CFG_HWC_1BITMOD_MASK 0x04000000 | ||
| 220 | #define CFG_HWC_1BITENA(mn) ((mn) << 25) | ||
| 221 | #define CFG_HWC_1BITENA_MASK 0x02000000 | ||
| 222 | #define CFG_HWC_ENA(cn) ((cn) << 24) | ||
| 223 | #define CFG_HWC_ENA_MASK 0x01000000 | ||
| 224 | #define CFG_DMAFORMAT(dmaformat) ((dmaformat) << 20) | ||
| 225 | #define CFG_DMAFORMAT_MASK 0x00F00000 | ||
| 226 | #define CFG_GRAFORMAT(graformat) ((graformat) << 16) | ||
| 227 | #define CFG_GRAFORMAT_MASK 0x000F0000 | ||
| 228 | /* for graphic part */ | ||
| 229 | #define CFG_GRA_FTOGGLE(toggle) ((toggle) << 15) | ||
| 230 | #define CFG_GRA_FTOGGLE_MASK 0x00008000 | ||
| 231 | #define CFG_GRA_HSMOOTH(smooth) ((smooth) << 14) | ||
| 232 | #define CFG_GRA_HSMOOTH_MASK 0x00004000 | ||
| 233 | #define CFG_GRA_TSTMODE(test) ((test) << 13) | ||
| 234 | #define CFG_GRA_TSTMODE_MASK 0x00002000 | ||
| 235 | #define CFG_GRA_SWAPRB(swap) ((swap) << 12) | ||
| 236 | #define CFG_GRA_SWAPRB_MASK 0x00001000 | ||
| 237 | #define CFG_GRA_SWAPUV(swap) ((swap) << 11) | ||
| 238 | #define CFG_GRA_SWAPUV_MASK 0x00000800 | ||
| 239 | #define CFG_GRA_SWAPYU(swap) ((swap) << 10) | ||
| 240 | #define CFG_GRA_SWAPYU_MASK 0x00000400 | ||
| 241 | #define CFG_YUV2RGB_GRA(cvrt) ((cvrt) << 9) | ||
| 242 | #define CFG_YUV2RGB_GRA_MASK 0x00000200 | ||
| 243 | #define CFG_GRA_ENA(gra) ((gra) << 8) | ||
| 244 | #define CFG_GRA_ENA_MASK 0x00000100 | ||
| 245 | /* for video part */ | ||
| 246 | #define CFG_DMA_FTOGGLE(toggle) ((toggle) << 7) | ||
| 247 | #define CFG_DMA_FTOGGLE_MASK 0x00000080 | ||
| 248 | #define CFG_DMA_HSMOOTH(smooth) ((smooth) << 6) | ||
| 249 | #define CFG_DMA_HSMOOTH_MASK 0x00000040 | ||
| 250 | #define CFG_DMA_TSTMODE(test) ((test) << 5) | ||
| 251 | #define CFG_DMA_TSTMODE_MASK 0x00000020 | ||
| 252 | #define CFG_DMA_SWAPRB(swap) ((swap) << 4) | ||
| 253 | #define CFG_DMA_SWAPRB_MASK 0x00000010 | ||
| 254 | #define CFG_DMA_SWAPUV(swap) ((swap) << 3) | ||
| 255 | #define CFG_DMA_SWAPUV_MASK 0x00000008 | ||
| 256 | #define CFG_DMA_SWAPYU(swap) ((swap) << 2) | ||
| 257 | #define CFG_DMA_SWAPYU_MASK 0x00000004 | ||
| 258 | #define CFG_DMA_SWAP_MASK 0x0000001C | ||
| 259 | #define CFG_YUV2RGB_DMA(cvrt) ((cvrt) << 1) | ||
| 260 | #define CFG_YUV2RGB_DMA_MASK 0x00000002 | ||
| 261 | #define CFG_DMA_ENA(video) (video) | ||
| 262 | #define CFG_DMA_ENA_MASK 0x00000001 | ||
| 263 | |||
| 264 | /* DMA Control 1 Register */ | ||
| 265 | #define LCD_SPU_DMA_CTRL1 0x0194 | ||
| 266 | #define CFG_FRAME_TRIG(trig) ((trig) << 31) | ||
| 267 | #define CFG_FRAME_TRIG_MASK 0x80000000 | ||
| 268 | #define CFG_VSYNC_TRIG(trig) ((trig) << 28) | ||
| 269 | #define CFG_VSYNC_TRIG_MASK 0x70000000 | ||
| 270 | #define CFG_VSYNC_INV(inv) ((inv) << 27) | ||
| 271 | #define CFG_VSYNC_INV_MASK 0x08000000 | ||
| 272 | #define CFG_COLOR_KEY_MODE(cmode) ((cmode) << 24) | ||
| 273 | #define CFG_COLOR_KEY_MASK 0x07000000 | ||
| 274 | #define CFG_CARRY(carry) ((carry) << 23) | ||
| 275 | #define CFG_CARRY_MASK 0x00800000 | ||
| 276 | #define CFG_LNBUF_ENA(lnbuf) ((lnbuf) << 22) | ||
| 277 | #define CFG_LNBUF_ENA_MASK 0x00400000 | ||
| 278 | #define CFG_GATED_ENA(gated) ((gated) << 21) | ||
| 279 | #define CFG_GATED_ENA_MASK 0x00200000 | ||
| 280 | #define CFG_PWRDN_ENA(power) ((power) << 20) | ||
| 281 | #define CFG_PWRDN_ENA_MASK 0x00100000 | ||
| 282 | #define CFG_DSCALE(dscale) ((dscale) << 18) | ||
| 283 | #define CFG_DSCALE_MASK 0x000C0000 | ||
| 284 | #define CFG_ALPHA_MODE(amode) ((amode) << 16) | ||
| 285 | #define CFG_ALPHA_MODE_MASK 0x00030000 | ||
| 286 | #define CFG_ALPHA(alpha) ((alpha) << 8) | ||
| 287 | #define CFG_ALPHA_MASK 0x0000FF00 | ||
| 288 | #define CFG_PXLCMD(pxlcmd) (pxlcmd) | ||
| 289 | #define CFG_PXLCMD_MASK 0x000000FF | ||
| 290 | |||
| 291 | /* SRAM Control Register */ | ||
| 292 | #define LCD_SPU_SRAM_CTRL 0x0198 | ||
| 293 | #define CFG_SRAM_INIT_WR_RD(mode) ((mode) << 14) | ||
| 294 | #define CFG_SRAM_INIT_WR_RD_MASK 0x0000C000 | ||
| 295 | #define CFG_SRAM_ADDR_LCDID(id) ((id) << 8) | ||
| 296 | #define CFG_SRAM_ADDR_LCDID_MASK 0x00000F00 | ||
| 297 | #define CFG_SRAM_ADDR(addr) (addr) | ||
| 298 | #define CFG_SRAM_ADDR_MASK 0x000000FF | ||
| 299 | |||
| 300 | /* SRAM Write Data Register */ | ||
| 301 | #define LCD_SPU_SRAM_WRDAT 0x019C | ||
| 302 | |||
| 303 | /* SRAM RTC/WTC Control Register */ | ||
| 304 | #define LCD_SPU_SRAM_PARA0 0x01A0 | ||
| 305 | |||
| 306 | /* SRAM Power Down Control Register */ | ||
| 307 | #define LCD_SPU_SRAM_PARA1 0x01A4 | ||
| 308 | #define CFG_CSB_256x32(hwc) ((hwc) << 15) /* HWC */ | ||
| 309 | #define CFG_CSB_256x32_MASK 0x00008000 | ||
| 310 | #define CFG_CSB_256x24(palette) ((palette) << 14) /* Palette */ | ||
| 311 | #define CFG_CSB_256x24_MASK 0x00004000 | ||
| 312 | #define CFG_CSB_256x8(gamma) ((gamma) << 13) /* Gamma */ | ||
| 313 | #define CFG_CSB_256x8_MASK 0x00002000 | ||
| 314 | #define CFG_PDWN256x32(pdwn) ((pdwn) << 7) /* HWC */ | ||
| 315 | #define CFG_PDWN256x32_MASK 0x00000080 | ||
| 316 | #define CFG_PDWN256x24(pdwn) ((pdwn) << 6) /* Palette */ | ||
| 317 | #define CFG_PDWN256x24_MASK 0x00000040 | ||
| 318 | #define CFG_PDWN256x8(pdwn) ((pdwn) << 5) /* Gamma */ | ||
| 319 | #define CFG_PDWN256x8_MASK 0x00000020 | ||
| 320 | #define CFG_PDWN32x32(pdwn) ((pdwn) << 3) | ||
| 321 | #define CFG_PDWN32x32_MASK 0x00000008 | ||
| 322 | #define CFG_PDWN16x66(pdwn) ((pdwn) << 2) | ||
| 323 | #define CFG_PDWN16x66_MASK 0x00000004 | ||
| 324 | #define CFG_PDWN32x66(pdwn) ((pdwn) << 1) | ||
| 325 | #define CFG_PDWN32x66_MASK 0x00000002 | ||
| 326 | #define CFG_PDWN64x66(pdwn) (pdwn) | ||
| 327 | #define CFG_PDWN64x66_MASK 0x00000001 | ||
| 328 | |||
| 329 | /* Smart or Dumb Panel Clock Divider */ | ||
| 330 | #define LCD_CFG_SCLK_DIV 0x01A8 | ||
| 331 | #define SCLK_SOURCE_SELECT(src) ((src) << 31) | ||
| 332 | #define SCLK_SOURCE_SELECT_MASK 0x80000000 | ||
| 333 | #define CLK_FRACDIV(frac) ((frac) << 16) | ||
| 334 | #define CLK_FRACDIV_MASK 0x0FFF0000 | ||
| 335 | #define CLK_INT_DIV(div) (div) | ||
| 336 | #define CLK_INT_DIV_MASK 0x0000FFFF | ||
| 337 | |||
| 338 | /* Video Contrast Register */ | ||
| 339 | #define LCD_SPU_CONTRAST 0x01AC | ||
| 340 | #define CFG_BRIGHTNESS(bright) ((bright) << 16) | ||
| 341 | #define CFG_BRIGHTNESS_MASK 0xFFFF0000 | ||
| 342 | #define CFG_CONTRAST(contrast) (contrast) | ||
| 343 | #define CFG_CONTRAST_MASK 0x0000FFFF | ||
| 344 | |||
| 345 | /* Video Saturation Register */ | ||
| 346 | #define LCD_SPU_SATURATION 0x01B0 | ||
| 347 | #define CFG_C_MULTS(mult) ((mult) << 16) | ||
| 348 | #define CFG_C_MULTS_MASK 0xFFFF0000 | ||
| 349 | #define CFG_SATURATION(sat) (sat) | ||
| 350 | #define CFG_SATURATION_MASK 0x0000FFFF | ||
| 351 | |||
| 352 | /* Video Hue Adjust Register */ | ||
| 353 | #define LCD_SPU_CBSH_HUE 0x01B4 | ||
| 354 | #define CFG_SIN0(sin0) ((sin0) << 16) | ||
| 355 | #define CFG_SIN0_MASK 0xFFFF0000 | ||
| 356 | #define CFG_COS0(con0) (con0) | ||
| 357 | #define CFG_COS0_MASK 0x0000FFFF | ||
| 358 | |||
| 359 | /* Dump LCD Panel Control Register */ | ||
| 360 | #define LCD_SPU_DUMB_CTRL 0x01B8 | ||
| 361 | #define CFG_DUMBMODE(mode) ((mode) << 28) | ||
| 362 | #define CFG_DUMBMODE_MASK 0xF0000000 | ||
| 363 | #define CFG_LCDGPIO_O(data) ((data) << 20) | ||
| 364 | #define CFG_LCDGPIO_O_MASK 0x0FF00000 | ||
| 365 | #define CFG_LCDGPIO_ENA(gpio) ((gpio) << 12) | ||
| 366 | #define CFG_LCDGPIO_ENA_MASK 0x000FF000 | ||
| 367 | #define CFG_BIAS_OUT(bias) ((bias) << 8) | ||
| 368 | #define CFG_BIAS_OUT_MASK 0x00000100 | ||
| 369 | #define CFG_REVERSE_RGB(rRGB) ((rRGB) << 7) | ||
| 370 | #define CFG_REVERSE_RGB_MASK 0x00000080 | ||
| 371 | #define CFG_INV_COMPBLANK(blank) ((blank) << 6) | ||
| 372 | #define CFG_INV_COMPBLANK_MASK 0x00000040 | ||
| 373 | #define CFG_INV_COMPSYNC(sync) ((sync) << 5) | ||
| 374 | #define CFG_INV_COMPSYNC_MASK 0x00000020 | ||
| 375 | #define CFG_INV_HENA(hena) ((hena) << 4) | ||
| 376 | #define CFG_INV_HENA_MASK 0x00000010 | ||
| 377 | #define CFG_INV_VSYNC(vsync) ((vsync) << 3) | ||
| 378 | #define CFG_INV_VSYNC_MASK 0x00000008 | ||
| 379 | #define CFG_INV_HSYNC(hsync) ((hsync) << 2) | ||
| 380 | #define CFG_INV_HSYNC_MASK 0x00000004 | ||
| 381 | #define CFG_INV_PCLK(pclk) ((pclk) << 1) | ||
| 382 | #define CFG_INV_PCLK_MASK 0x00000002 | ||
| 383 | #define CFG_DUMB_ENA(dumb) (dumb) | ||
| 384 | #define CFG_DUMB_ENA_MASK 0x00000001 | ||
| 385 | |||
| 386 | /* LCD I/O Pads Control Register */ | ||
| 387 | #define SPU_IOPAD_CONTROL 0x01BC | ||
| 388 | #define CFG_GRA_VM_ENA(vm) ((vm) << 15) /* gfx */ | ||
| 389 | #define CFG_GRA_VM_ENA_MASK 0x00008000 | ||
| 390 | #define CFG_DMA_VM_ENA(vm) ((vm) << 13) /* video */ | ||
| 391 | #define CFG_DMA_VM_ENA_MASK 0x00002000 | ||
| 392 | #define CFG_CMD_VM_ENA(vm) ((vm) << 13) | ||
| 393 | #define CFG_CMD_VM_ENA_MASK 0x00000800 | ||
| 394 | #define CFG_CSC(csc) ((csc) << 8) /* csc */ | ||
| 395 | #define CFG_CSC_MASK 0x00000300 | ||
| 396 | #define CFG_AXICTRL(axi) ((axi) << 4) | ||
| 397 | #define CFG_AXICTRL_MASK 0x000000F0 | ||
| 398 | #define CFG_IOPADMODE(iopad) (iopad) | ||
| 399 | #define CFG_IOPADMODE_MASK 0x0000000F | ||
| 400 | |||
| 401 | /* LCD Interrupt Control Register */ | ||
| 402 | #define SPU_IRQ_ENA 0x01C0 | ||
| 403 | #define DMA_FRAME_IRQ0_ENA(irq) ((irq) << 31) | ||
| 404 | #define DMA_FRAME_IRQ0_ENA_MASK 0x80000000 | ||
| 405 | #define DMA_FRAME_IRQ1_ENA(irq) ((irq) << 30) | ||
| 406 | #define DMA_FRAME_IRQ1_ENA_MASK 0x40000000 | ||
| 407 | #define DMA_FF_UNDERFLOW_ENA(ff) ((ff) << 29) | ||
| 408 | #define DMA_FF_UNDERFLOW_ENA_MASK 0x20000000 | ||
| 409 | #define GRA_FRAME_IRQ0_ENA(irq) ((irq) << 27) | ||
| 410 | #define GRA_FRAME_IRQ0_ENA_MASK 0x08000000 | ||
| 411 | #define GRA_FRAME_IRQ1_ENA(irq) ((irq) << 26) | ||
| 412 | #define GRA_FRAME_IRQ1_ENA_MASK 0x04000000 | ||
| 413 | #define GRA_FF_UNDERFLOW_ENA(ff) ((ff) << 25) | ||
| 414 | #define GRA_FF_UNDERFLOW_ENA_MASK 0x02000000 | ||
| 415 | #define VSYNC_IRQ_ENA(vsync_irq) ((vsync_irq) << 23) | ||
| 416 | #define VSYNC_IRQ_ENA_MASK 0x00800000 | ||
| 417 | #define DUMB_FRAMEDONE_ENA(fdone) ((fdone) << 22) | ||
| 418 | #define DUMB_FRAMEDONE_ENA_MASK 0x00400000 | ||
| 419 | #define TWC_FRAMEDONE_ENA(fdone) ((fdone) << 21) | ||
| 420 | #define TWC_FRAMEDONE_ENA_MASK 0x00200000 | ||
| 421 | #define HWC_FRAMEDONE_ENA(fdone) ((fdone) << 20) | ||
| 422 | #define HWC_FRAMEDONE_ENA_MASK 0x00100000 | ||
| 423 | #define SLV_IRQ_ENA(irq) ((irq) << 19) | ||
| 424 | #define SLV_IRQ_ENA_MASK 0x00080000 | ||
| 425 | #define SPI_IRQ_ENA(irq) ((irq) << 18) | ||
| 426 | #define SPI_IRQ_ENA_MASK 0x00040000 | ||
| 427 | #define PWRDN_IRQ_ENA(irq) ((irq) << 17) | ||
| 428 | #define PWRDN_IRQ_ENA_MASK 0x00020000 | ||
| 429 | #define ERR_IRQ_ENA(irq) ((irq) << 16) | ||
| 430 | #define ERR_IRQ_ENA_MASK 0x00010000 | ||
| 431 | #define CLEAN_SPU_IRQ_ISR(irq) (irq) | ||
| 432 | #define CLEAN_SPU_IRQ_ISR_MASK 0x0000FFFF | ||
| 433 | |||
| 434 | /* LCD Interrupt Status Register */ | ||
| 435 | #define SPU_IRQ_ISR 0x01C4 | ||
| 436 | #define DMA_FRAME_IRQ0(irq) ((irq) << 31) | ||
| 437 | #define DMA_FRAME_IRQ0_MASK 0x80000000 | ||
| 438 | #define DMA_FRAME_IRQ1(irq) ((irq) << 30) | ||
| 439 | #define DMA_FRAME_IRQ1_MASK 0x40000000 | ||
| 440 | #define DMA_FF_UNDERFLOW(ff) ((ff) << 29) | ||
| 441 | #define DMA_FF_UNDERFLOW_MASK 0x20000000 | ||
| 442 | #define GRA_FRAME_IRQ0(irq) ((irq) << 27) | ||
| 443 | #define GRA_FRAME_IRQ0_MASK 0x08000000 | ||
| 444 | #define GRA_FRAME_IRQ1(irq) ((irq) << 26) | ||
| 445 | #define GRA_FRAME_IRQ1_MASK 0x04000000 | ||
| 446 | #define GRA_FF_UNDERFLOW(ff) ((ff) << 25) | ||
| 447 | #define GRA_FF_UNDERFLOW_MASK 0x02000000 | ||
| 448 | #define VSYNC_IRQ(vsync_irq) ((vsync_irq) << 23) | ||
| 449 | #define VSYNC_IRQ_MASK 0x00800000 | ||
| 450 | #define DUMB_FRAMEDONE(fdone) ((fdone) << 22) | ||
| 451 | #define DUMB_FRAMEDONE_MASK 0x00400000 | ||
| 452 | #define TWC_FRAMEDONE(fdone) ((fdone) << 21) | ||
| 453 | #define TWC_FRAMEDONE_MASK 0x00200000 | ||
| 454 | #define HWC_FRAMEDONE(fdone) ((fdone) << 20) | ||
| 455 | #define HWC_FRAMEDONE_MASK 0x00100000 | ||
| 456 | #define SLV_IRQ(irq) ((irq) << 19) | ||
| 457 | #define SLV_IRQ_MASK 0x00080000 | ||
| 458 | #define SPI_IRQ(irq) ((irq) << 18) | ||
| 459 | #define SPI_IRQ_MASK 0x00040000 | ||
| 460 | #define PWRDN_IRQ(irq) ((irq) << 17) | ||
| 461 | #define PWRDN_IRQ_MASK 0x00020000 | ||
| 462 | #define ERR_IRQ(irq) ((irq) << 16) | ||
| 463 | #define ERR_IRQ_MASK 0x00010000 | ||
| 464 | /* read-only */ | ||
| 465 | #define DMA_FRAME_IRQ0_LEVEL_MASK 0x00008000 | ||
| 466 | #define DMA_FRAME_IRQ1_LEVEL_MASK 0x00004000 | ||
| 467 | #define DMA_FRAME_CNT_ISR_MASK 0x00003000 | ||
| 468 | #define GRA_FRAME_IRQ0_LEVEL_MASK 0x00000800 | ||
| 469 | #define GRA_FRAME_IRQ1_LEVEL_MASK 0x00000400 | ||
| 470 | #define GRA_FRAME_CNT_ISR_MASK 0x00000300 | ||
| 471 | #define VSYNC_IRQ_LEVEL_MASK 0x00000080 | ||
| 472 | #define DUMB_FRAMEDONE_LEVEL_MASK 0x00000040 | ||
| 473 | #define TWC_FRAMEDONE_LEVEL_MASK 0x00000020 | ||
| 474 | #define HWC_FRAMEDONE_LEVEL_MASK 0x00000010 | ||
| 475 | #define SLV_FF_EMPTY_MASK 0x00000008 | ||
| 476 | #define DMA_FF_ALLEMPTY_MASK 0x00000004 | ||
| 477 | #define GRA_FF_ALLEMPTY_MASK 0x00000002 | ||
| 478 | #define PWRDN_IRQ_LEVEL_MASK 0x00000001 | ||
| 479 | |||
| 480 | |||
| 481 | /* | ||
| 482 | * defined Video Memory Color format for DMA control 0 register | ||
| 483 | * DMA0 bit[23:20] | ||
| 484 | */ | ||
| 485 | #define VMODE_RGB565 0x0 | ||
| 486 | #define VMODE_RGB1555 0x1 | ||
| 487 | #define VMODE_RGB888PACKED 0x2 | ||
| 488 | #define VMODE_RGB888UNPACKED 0x3 | ||
| 489 | #define VMODE_RGBA888 0x4 | ||
| 490 | #define VMODE_YUV422PACKED 0x5 | ||
| 491 | #define VMODE_YUV422PLANAR 0x6 | ||
| 492 | #define VMODE_YUV420PLANAR 0x7 | ||
| 493 | #define VMODE_SMPNCMD 0x8 | ||
| 494 | #define VMODE_PALETTE4BIT 0x9 | ||
| 495 | #define VMODE_PALETTE8BIT 0xa | ||
| 496 | #define VMODE_RESERVED 0xb | ||
| 497 | |||
| 498 | /* | ||
| 499 | * defined Graphic Memory Color format for DMA control 0 register | ||
| 500 | * DMA0 bit[19:16] | ||
| 501 | */ | ||
| 502 | #define GMODE_RGB565 0x0 | ||
| 503 | #define GMODE_RGB1555 0x1 | ||
| 504 | #define GMODE_RGB888PACKED 0x2 | ||
| 505 | #define GMODE_RGB888UNPACKED 0x3 | ||
| 506 | #define GMODE_RGBA888 0x4 | ||
| 507 | #define GMODE_YUV422PACKED 0x5 | ||
| 508 | #define GMODE_YUV422PLANAR 0x6 | ||
| 509 | #define GMODE_YUV420PLANAR 0x7 | ||
| 510 | #define GMODE_SMPNCMD 0x8 | ||
| 511 | #define GMODE_PALETTE4BIT 0x9 | ||
| 512 | #define GMODE_PALETTE8BIT 0xa | ||
| 513 | #define GMODE_RESERVED 0xb | ||
| 514 | |||
| 515 | /* | ||
| 516 | * define for DMA control 1 register | ||
| 517 | */ | ||
| 518 | #define DMA1_FRAME_TRIG 31 /* bit location */ | ||
| 519 | #define DMA1_VSYNC_MODE 28 | ||
| 520 | #define DMA1_VSYNC_INV 27 | ||
| 521 | #define DMA1_CKEY 24 | ||
| 522 | #define DMA1_CARRY 23 | ||
| 523 | #define DMA1_LNBUF_ENA 22 | ||
| 524 | #define DMA1_GATED_ENA 21 | ||
| 525 | #define DMA1_PWRDN_ENA 20 | ||
| 526 | #define DMA1_DSCALE 18 | ||
| 527 | #define DMA1_ALPHA_MODE 16 | ||
| 528 | #define DMA1_ALPHA 08 | ||
| 529 | #define DMA1_PXLCMD 00 | ||
| 530 | |||
| 531 | /* | ||
| 532 | * defined for Configure Dumb Mode | ||
| 533 | * DUMB LCD Panel bit[31:28] | ||
| 534 | */ | ||
| 535 | #define DUMB16_RGB565_0 0x0 | ||
| 536 | #define DUMB16_RGB565_1 0x1 | ||
| 537 | #define DUMB18_RGB666_0 0x2 | ||
| 538 | #define DUMB18_RGB666_1 0x3 | ||
| 539 | #define DUMB12_RGB444_0 0x4 | ||
| 540 | #define DUMB12_RGB444_1 0x5 | ||
| 541 | #define DUMB24_RGB888_0 0x6 | ||
| 542 | #define DUMB_BLANK 0x7 | ||
| 543 | |||
| 544 | /* | ||
| 545 | * defined for Configure I/O Pin Allocation Mode | ||
| 546 | * LCD LCD I/O Pads control register bit[3:0] | ||
| 547 | */ | ||
| 548 | #define IOPAD_DUMB24 0x0 | ||
| 549 | #define IOPAD_DUMB18SPI 0x1 | ||
| 550 | #define IOPAD_DUMB18GPIO 0x2 | ||
| 551 | #define IOPAD_DUMB16SPI 0x3 | ||
| 552 | #define IOPAD_DUMB16GPIO 0x4 | ||
| 553 | #define IOPAD_DUMB12 0x5 | ||
| 554 | #define IOPAD_SMART18SPI 0x6 | ||
| 555 | #define IOPAD_SMART16SPI 0x7 | ||
| 556 | #define IOPAD_SMART8BOTH 0x8 | ||
| 557 | |||
| 558 | #endif /* __PXA168FB_H__ */ | ||
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 5eb8f21da82e..5744cac4864b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
| @@ -231,14 +231,14 @@ config DAVINCI_WATCHDOG | |||
| 231 | NOTE: once enabled, this timer cannot be disabled. | 231 | NOTE: once enabled, this timer cannot be disabled. |
| 232 | Say N if you are unsure. | 232 | Say N if you are unsure. |
| 233 | 233 | ||
| 234 | config ORION5X_WATCHDOG | 234 | config ORION_WATCHDOG |
| 235 | tristate "Orion5x watchdog" | 235 | tristate "Orion watchdog" |
| 236 | depends on ARCH_ORION5X | 236 | depends on ARCH_ORION5X || ARCH_KIRKWOOD |
| 237 | help | 237 | help |
| 238 | Say Y here if to include support for the watchdog timer | 238 | Say Y here if to include support for the watchdog timer |
| 239 | in the Orion5x ARM SoCs. | 239 | in the Marvell Orion5x and Kirkwood ARM SoCs. |
| 240 | To compile this driver as a module, choose M here: the | 240 | To compile this driver as a module, choose M here: the |
| 241 | module will be called orion5x_wdt. | 241 | module will be called orion_wdt. |
| 242 | 242 | ||
| 243 | # AVR32 Architecture | 243 | # AVR32 Architecture |
| 244 | 244 | ||
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 7f8c56b14f58..c3afa14d5be1 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
| @@ -40,7 +40,7 @@ obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o | |||
| 40 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o | 40 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o |
| 41 | obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o | 41 | obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o |
| 42 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o | 42 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o |
| 43 | obj-$(CONFIG_ORION5X_WATCHDOG) += orion5x_wdt.o | 43 | obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o |
| 44 | 44 | ||
| 45 | # AVR32 Architecture | 45 | # AVR32 Architecture |
| 46 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o | 46 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o |
diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion_wdt.c index 2cde568e4fb0..2d9fb96a9ee9 100644 --- a/drivers/watchdog/orion5x_wdt.c +++ b/drivers/watchdog/orion_wdt.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/watchdog/orion5x_wdt.c | 2 | * drivers/watchdog/orion_wdt.c |
| 3 | * | 3 | * |
| 4 | * Watchdog driver for Orion5x processors | 4 | * Watchdog driver for Orion/Kirkwood processors |
| 5 | * | 5 | * |
| 6 | * Author: Sylver Bruneau <sylver.bruneau@googlemail.com> | 6 | * Author: Sylver Bruneau <sylver.bruneau@googlemail.com> |
| 7 | * | 7 | * |
| @@ -23,7 +23,7 @@ | |||
| 23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| 24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
| 25 | #include <mach/bridge-regs.h> | 25 | #include <mach/bridge-regs.h> |
| 26 | #include <plat/orion5x_wdt.h> | 26 | #include <plat/orion_wdt.h> |
| 27 | 27 | ||
| 28 | /* | 28 | /* |
| 29 | * Watchdog timer block registers. | 29 | * Watchdog timer block registers. |
| @@ -43,7 +43,7 @@ static unsigned int wdt_tclk; | |||
| 43 | static unsigned long wdt_status; | 43 | static unsigned long wdt_status; |
| 44 | static spinlock_t wdt_lock; | 44 | static spinlock_t wdt_lock; |
| 45 | 45 | ||
| 46 | static void orion5x_wdt_ping(void) | 46 | static void orion_wdt_ping(void) |
| 47 | { | 47 | { |
| 48 | spin_lock(&wdt_lock); | 48 | spin_lock(&wdt_lock); |
| 49 | 49 | ||
| @@ -53,7 +53,7 @@ static void orion5x_wdt_ping(void) | |||
| 53 | spin_unlock(&wdt_lock); | 53 | spin_unlock(&wdt_lock); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | static void orion5x_wdt_enable(void) | 56 | static void orion_wdt_enable(void) |
| 57 | { | 57 | { |
| 58 | u32 reg; | 58 | u32 reg; |
| 59 | 59 | ||
| @@ -73,23 +73,23 @@ static void orion5x_wdt_enable(void) | |||
| 73 | writel(reg, TIMER_CTRL); | 73 | writel(reg, TIMER_CTRL); |
| 74 | 74 | ||
| 75 | /* Enable reset on watchdog */ | 75 | /* Enable reset on watchdog */ |
| 76 | reg = readl(CPU_RESET_MASK); | 76 | reg = readl(RSTOUTn_MASK); |
| 77 | reg |= WDT_RESET; | 77 | reg |= WDT_RESET_OUT_EN; |
| 78 | writel(reg, CPU_RESET_MASK); | 78 | writel(reg, RSTOUTn_MASK); |
| 79 | 79 | ||
| 80 | spin_unlock(&wdt_lock); | 80 | spin_unlock(&wdt_lock); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static void orion5x_wdt_disable(void) | 83 | static void orion_wdt_disable(void) |
| 84 | { | 84 | { |
| 85 | u32 reg; | 85 | u32 reg; |
| 86 | 86 | ||
| 87 | spin_lock(&wdt_lock); | 87 | spin_lock(&wdt_lock); |
| 88 | 88 | ||
| 89 | /* Disable reset on watchdog */ | 89 | /* Disable reset on watchdog */ |
| 90 | reg = readl(CPU_RESET_MASK); | 90 | reg = readl(RSTOUTn_MASK); |
| 91 | reg &= ~WDT_RESET; | 91 | reg &= ~WDT_RESET_OUT_EN; |
| 92 | writel(reg, CPU_RESET_MASK); | 92 | writel(reg, RSTOUTn_MASK); |
| 93 | 93 | ||
| 94 | /* Disable watchdog timer */ | 94 | /* Disable watchdog timer */ |
| 95 | reg = readl(TIMER_CTRL); | 95 | reg = readl(TIMER_CTRL); |
| @@ -99,7 +99,7 @@ static void orion5x_wdt_disable(void) | |||
| 99 | spin_unlock(&wdt_lock); | 99 | spin_unlock(&wdt_lock); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static int orion5x_wdt_get_timeleft(int *time_left) | 102 | static int orion_wdt_get_timeleft(int *time_left) |
| 103 | { | 103 | { |
| 104 | spin_lock(&wdt_lock); | 104 | spin_lock(&wdt_lock); |
| 105 | *time_left = readl(WDT_VAL) / wdt_tclk; | 105 | *time_left = readl(WDT_VAL) / wdt_tclk; |
| @@ -107,16 +107,16 @@ static int orion5x_wdt_get_timeleft(int *time_left) | |||
| 107 | return 0; | 107 | return 0; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | static int orion5x_wdt_open(struct inode *inode, struct file *file) | 110 | static int orion_wdt_open(struct inode *inode, struct file *file) |
| 111 | { | 111 | { |
| 112 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | 112 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) |
| 113 | return -EBUSY; | 113 | return -EBUSY; |
| 114 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | 114 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); |
| 115 | orion5x_wdt_enable(); | 115 | orion_wdt_enable(); |
| 116 | return nonseekable_open(inode, file); | 116 | return nonseekable_open(inode, file); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static ssize_t orion5x_wdt_write(struct file *file, const char *data, | 119 | static ssize_t orion_wdt_write(struct file *file, const char *data, |
| 120 | size_t len, loff_t *ppos) | 120 | size_t len, loff_t *ppos) |
| 121 | { | 121 | { |
| 122 | if (len) { | 122 | if (len) { |
| @@ -133,18 +133,18 @@ static ssize_t orion5x_wdt_write(struct file *file, const char *data, | |||
| 133 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | 133 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); |
| 134 | } | 134 | } |
| 135 | } | 135 | } |
| 136 | orion5x_wdt_ping(); | 136 | orion_wdt_ping(); |
| 137 | } | 137 | } |
| 138 | return len; | 138 | return len; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | static int orion5x_wdt_settimeout(int new_time) | 141 | static int orion_wdt_settimeout(int new_time) |
| 142 | { | 142 | { |
| 143 | if ((new_time <= 0) || (new_time > wdt_max_duration)) | 143 | if ((new_time <= 0) || (new_time > wdt_max_duration)) |
| 144 | return -EINVAL; | 144 | return -EINVAL; |
| 145 | 145 | ||
| 146 | /* Set new watchdog time to be used when | 146 | /* Set new watchdog time to be used when |
| 147 | * orion5x_wdt_enable() or orion5x_wdt_ping() is called. */ | 147 | * orion_wdt_enable() or orion_wdt_ping() is called. */ |
| 148 | heartbeat = new_time; | 148 | heartbeat = new_time; |
| 149 | return 0; | 149 | return 0; |
| 150 | } | 150 | } |
| @@ -152,10 +152,10 @@ static int orion5x_wdt_settimeout(int new_time) | |||
| 152 | static const struct watchdog_info ident = { | 152 | static const struct watchdog_info ident = { |
| 153 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | | 153 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | |
| 154 | WDIOF_KEEPALIVEPING, | 154 | WDIOF_KEEPALIVEPING, |
| 155 | .identity = "Orion5x Watchdog", | 155 | .identity = "Orion Watchdog", |
| 156 | }; | 156 | }; |
| 157 | 157 | ||
| 158 | static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | 158 | static long orion_wdt_ioctl(struct file *file, unsigned int cmd, |
| 159 | unsigned long arg) | 159 | unsigned long arg) |
| 160 | { | 160 | { |
| 161 | int ret = -ENOTTY; | 161 | int ret = -ENOTTY; |
| @@ -173,7 +173,7 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
| 173 | break; | 173 | break; |
| 174 | 174 | ||
| 175 | case WDIOC_KEEPALIVE: | 175 | case WDIOC_KEEPALIVE: |
| 176 | orion5x_wdt_ping(); | 176 | orion_wdt_ping(); |
| 177 | ret = 0; | 177 | ret = 0; |
| 178 | break; | 178 | break; |
| 179 | 179 | ||
| @@ -182,11 +182,11 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
| 182 | if (ret) | 182 | if (ret) |
| 183 | break; | 183 | break; |
| 184 | 184 | ||
| 185 | if (orion5x_wdt_settimeout(time)) { | 185 | if (orion_wdt_settimeout(time)) { |
| 186 | ret = -EINVAL; | 186 | ret = -EINVAL; |
| 187 | break; | 187 | break; |
| 188 | } | 188 | } |
| 189 | orion5x_wdt_ping(); | 189 | orion_wdt_ping(); |
| 190 | /* Fall through */ | 190 | /* Fall through */ |
| 191 | 191 | ||
| 192 | case WDIOC_GETTIMEOUT: | 192 | case WDIOC_GETTIMEOUT: |
| @@ -194,7 +194,7 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
| 194 | break; | 194 | break; |
| 195 | 195 | ||
| 196 | case WDIOC_GETTIMELEFT: | 196 | case WDIOC_GETTIMELEFT: |
| 197 | if (orion5x_wdt_get_timeleft(&time)) { | 197 | if (orion_wdt_get_timeleft(&time)) { |
| 198 | ret = -EINVAL; | 198 | ret = -EINVAL; |
| 199 | break; | 199 | break; |
| 200 | } | 200 | } |
| @@ -204,10 +204,10 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
| 204 | return ret; | 204 | return ret; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | static int orion5x_wdt_release(struct inode *inode, struct file *file) | 207 | static int orion_wdt_release(struct inode *inode, struct file *file) |
| 208 | { | 208 | { |
| 209 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | 209 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) |
| 210 | orion5x_wdt_disable(); | 210 | orion_wdt_disable(); |
| 211 | else | 211 | else |
| 212 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " | 212 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " |
| 213 | "timer will not stop\n"); | 213 | "timer will not stop\n"); |
| @@ -218,98 +218,98 @@ static int orion5x_wdt_release(struct inode *inode, struct file *file) | |||
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | 220 | ||
| 221 | static const struct file_operations orion5x_wdt_fops = { | 221 | static const struct file_operations orion_wdt_fops = { |
| 222 | .owner = THIS_MODULE, | 222 | .owner = THIS_MODULE, |
| 223 | .llseek = no_llseek, | 223 | .llseek = no_llseek, |
| 224 | .write = orion5x_wdt_write, | 224 | .write = orion_wdt_write, |
| 225 | .unlocked_ioctl = orion5x_wdt_ioctl, | 225 | .unlocked_ioctl = orion_wdt_ioctl, |
| 226 | .open = orion5x_wdt_open, | 226 | .open = orion_wdt_open, |
| 227 | .release = orion5x_wdt_release, | 227 | .release = orion_wdt_release, |
| 228 | }; | 228 | }; |
| 229 | 229 | ||
| 230 | static struct miscdevice orion5x_wdt_miscdev = { | 230 | static struct miscdevice orion_wdt_miscdev = { |
| 231 | .minor = WATCHDOG_MINOR, | 231 | .minor = WATCHDOG_MINOR, |
| 232 | .name = "watchdog", | 232 | .name = "watchdog", |
| 233 | .fops = &orion5x_wdt_fops, | 233 | .fops = &orion_wdt_fops, |
| 234 | }; | 234 | }; |
| 235 | 235 | ||
| 236 | static int __devinit orion5x_wdt_probe(struct platform_device *pdev) | 236 | static int __devinit orion_wdt_probe(struct platform_device *pdev) |
| 237 | { | 237 | { |
| 238 | struct orion5x_wdt_platform_data *pdata = pdev->dev.platform_data; | 238 | struct orion_wdt_platform_data *pdata = pdev->dev.platform_data; |
| 239 | int ret; | 239 | int ret; |
| 240 | 240 | ||
| 241 | if (pdata) { | 241 | if (pdata) { |
| 242 | wdt_tclk = pdata->tclk; | 242 | wdt_tclk = pdata->tclk; |
| 243 | } else { | 243 | } else { |
| 244 | printk(KERN_ERR "Orion5x Watchdog misses platform data\n"); | 244 | printk(KERN_ERR "Orion Watchdog misses platform data\n"); |
| 245 | return -ENODEV; | 245 | return -ENODEV; |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | if (orion5x_wdt_miscdev.parent) | 248 | if (orion_wdt_miscdev.parent) |
| 249 | return -EBUSY; | 249 | return -EBUSY; |
| 250 | orion5x_wdt_miscdev.parent = &pdev->dev; | 250 | orion_wdt_miscdev.parent = &pdev->dev; |
| 251 | 251 | ||
| 252 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; | 252 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; |
| 253 | if (orion5x_wdt_settimeout(heartbeat)) | 253 | if (orion_wdt_settimeout(heartbeat)) |
| 254 | heartbeat = wdt_max_duration; | 254 | heartbeat = wdt_max_duration; |
| 255 | 255 | ||
| 256 | ret = misc_register(&orion5x_wdt_miscdev); | 256 | ret = misc_register(&orion_wdt_miscdev); |
| 257 | if (ret) | 257 | if (ret) |
| 258 | return ret; | 258 | return ret; |
| 259 | 259 | ||
| 260 | printk(KERN_INFO "Orion5x Watchdog Timer: Initial timeout %d sec%s\n", | 260 | printk(KERN_INFO "Orion Watchdog Timer: Initial timeout %d sec%s\n", |
| 261 | heartbeat, nowayout ? ", nowayout" : ""); | 261 | heartbeat, nowayout ? ", nowayout" : ""); |
| 262 | return 0; | 262 | return 0; |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | static int __devexit orion5x_wdt_remove(struct platform_device *pdev) | 265 | static int __devexit orion_wdt_remove(struct platform_device *pdev) |
| 266 | { | 266 | { |
| 267 | int ret; | 267 | int ret; |
| 268 | 268 | ||
| 269 | if (test_bit(WDT_IN_USE, &wdt_status)) { | 269 | if (test_bit(WDT_IN_USE, &wdt_status)) { |
| 270 | orion5x_wdt_disable(); | 270 | orion_wdt_disable(); |
| 271 | clear_bit(WDT_IN_USE, &wdt_status); | 271 | clear_bit(WDT_IN_USE, &wdt_status); |
| 272 | } | 272 | } |
| 273 | 273 | ||
| 274 | ret = misc_deregister(&orion5x_wdt_miscdev); | 274 | ret = misc_deregister(&orion_wdt_miscdev); |
| 275 | if (!ret) | 275 | if (!ret) |
| 276 | orion5x_wdt_miscdev.parent = NULL; | 276 | orion_wdt_miscdev.parent = NULL; |
| 277 | 277 | ||
| 278 | return ret; | 278 | return ret; |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | static void orion5x_wdt_shutdown(struct platform_device *pdev) | 281 | static void orion_wdt_shutdown(struct platform_device *pdev) |
| 282 | { | 282 | { |
| 283 | if (test_bit(WDT_IN_USE, &wdt_status)) | 283 | if (test_bit(WDT_IN_USE, &wdt_status)) |
| 284 | orion5x_wdt_disable(); | 284 | orion_wdt_disable(); |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | static struct platform_driver orion5x_wdt_driver = { | 287 | static struct platform_driver orion_wdt_driver = { |
| 288 | .probe = orion5x_wdt_probe, | 288 | .probe = orion_wdt_probe, |
| 289 | .remove = __devexit_p(orion5x_wdt_remove), | 289 | .remove = __devexit_p(orion_wdt_remove), |
| 290 | .shutdown = orion5x_wdt_shutdown, | 290 | .shutdown = orion_wdt_shutdown, |
| 291 | .driver = { | 291 | .driver = { |
| 292 | .owner = THIS_MODULE, | 292 | .owner = THIS_MODULE, |
| 293 | .name = "orion5x_wdt", | 293 | .name = "orion_wdt", |
| 294 | }, | 294 | }, |
| 295 | }; | 295 | }; |
| 296 | 296 | ||
| 297 | static int __init orion5x_wdt_init(void) | 297 | static int __init orion_wdt_init(void) |
| 298 | { | 298 | { |
| 299 | spin_lock_init(&wdt_lock); | 299 | spin_lock_init(&wdt_lock); |
| 300 | return platform_driver_register(&orion5x_wdt_driver); | 300 | return platform_driver_register(&orion_wdt_driver); |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | static void __exit orion5x_wdt_exit(void) | 303 | static void __exit orion_wdt_exit(void) |
| 304 | { | 304 | { |
| 305 | platform_driver_unregister(&orion5x_wdt_driver); | 305 | platform_driver_unregister(&orion_wdt_driver); |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | module_init(orion5x_wdt_init); | 308 | module_init(orion_wdt_init); |
| 309 | module_exit(orion5x_wdt_exit); | 309 | module_exit(orion_wdt_exit); |
| 310 | 310 | ||
| 311 | MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>"); | 311 | MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>"); |
| 312 | MODULE_DESCRIPTION("Orion5x Processor Watchdog"); | 312 | MODULE_DESCRIPTION("Orion Processor Watchdog"); |
| 313 | 313 | ||
| 314 | module_param(heartbeat, int, 0); | 314 | module_param(heartbeat, int, 0); |
| 315 | MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds"); | 315 | MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds"); |
