aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/cdrom/gdrom.c10
-rw-r--r--drivers/mfd/Kconfig8
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/sh_mobile_sdhi.c145
-rw-r--r--drivers/mmc/host/Kconfig2
-rw-r--r--drivers/sh/intc.c123
-rw-r--r--drivers/sh/maple/maple.c4
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c32
8 files changed, 295 insertions, 30 deletions
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index a762283d2a21..e789e6c9a422 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -214,7 +214,7 @@ static void gdrom_spicommand(void *spi_string, int buflen)
214 gdrom_getsense(NULL); 214 gdrom_getsense(NULL);
215 return; 215 return;
216 } 216 }
217 outsw(PHYSADDR(GDROM_DATA_REG), cmd, 6); 217 outsw(GDROM_DATA_REG, cmd, 6);
218} 218}
219 219
220 220
@@ -298,7 +298,7 @@ static int gdrom_readtoc_cmd(struct gdromtoc *toc, int session)
298 err = -EINVAL; 298 err = -EINVAL;
299 goto cleanup_readtoc; 299 goto cleanup_readtoc;
300 } 300 }
301 insw(PHYSADDR(GDROM_DATA_REG), toc, tocsize/2); 301 insw(GDROM_DATA_REG, toc, tocsize/2);
302 if (gd.status & 0x01) 302 if (gd.status & 0x01)
303 err = -EINVAL; 303 err = -EINVAL;
304 304
@@ -449,7 +449,7 @@ static int gdrom_getsense(short *bufstring)
449 GDROM_DEFAULT_TIMEOUT); 449 GDROM_DEFAULT_TIMEOUT);
450 if (gd.pending) 450 if (gd.pending)
451 goto cleanup_sense; 451 goto cleanup_sense;
452 insw(PHYSADDR(GDROM_DATA_REG), &sense, sense_command->buflen/2); 452 insw(GDROM_DATA_REG, &sense, sense_command->buflen/2);
453 if (sense[1] & 40) { 453 if (sense[1] & 40) {
454 printk(KERN_INFO "GDROM: Drive not ready - command aborted\n"); 454 printk(KERN_INFO "GDROM: Drive not ready - command aborted\n");
455 goto cleanup_sense; 455 goto cleanup_sense;
@@ -586,7 +586,7 @@ static void gdrom_readdisk_dma(struct work_struct *work)
586 spin_unlock(&gdrom_lock); 586 spin_unlock(&gdrom_lock);
587 block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET; 587 block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET;
588 block_cnt = blk_rq_sectors(req)/GD_TO_BLK; 588 block_cnt = blk_rq_sectors(req)/GD_TO_BLK;
589 ctrl_outl(PHYSADDR(req->buffer), GDROM_DMA_STARTADDR_REG); 589 ctrl_outl(virt_to_phys(req->buffer), GDROM_DMA_STARTADDR_REG);
590 ctrl_outl(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG); 590 ctrl_outl(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG);
591 ctrl_outl(1, GDROM_DMA_DIRECTION_REG); 591 ctrl_outl(1, GDROM_DMA_DIRECTION_REG);
592 ctrl_outl(1, GDROM_DMA_ENABLE_REG); 592 ctrl_outl(1, GDROM_DMA_ENABLE_REG);
@@ -615,7 +615,7 @@ static void gdrom_readdisk_dma(struct work_struct *work)
615 cpu_relax(); 615 cpu_relax();
616 gd.pending = 1; 616 gd.pending = 1;
617 gd.transfer = 1; 617 gd.transfer = 1;
618 outsw(PHYSADDR(GDROM_DATA_REG), &read_command->cmd, 6); 618 outsw(GDROM_DATA_REG, &read_command->cmd, 6);
619 timeout = jiffies + HZ / 2; 619 timeout = jiffies + HZ / 2;
620 /* Wait for any pending DMA to finish */ 620 /* Wait for any pending DMA to finish */
621 while (ctrl_inb(GDROM_DMA_STATUS_REG) && 621 while (ctrl_inb(GDROM_DMA_STATUS_REG) &&
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 570be139f9df..96956b3cc178 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -35,6 +35,14 @@ config MFD_ASIC3
35 This driver supports the ASIC3 multifunction chip found on many 35 This driver supports the ASIC3 multifunction chip found on many
36 PDAs (mainly iPAQ and HTC based ones) 36 PDAs (mainly iPAQ and HTC based ones)
37 37
38config MFD_SH_MOBILE_SDHI
39 bool "Support for SuperH Mobile SDHI"
40 depends on SUPERH
41 select MFD_CORE
42 ---help---
43 This driver supports the SDHI hardware block found in many
44 SuperH Mobile SoCs.
45
38config MFD_DM355EVM_MSP 46config MFD_DM355EVM_MSP
39 bool "DaVinci DM355 EVM microcontroller" 47 bool "DaVinci DM355 EVM microcontroller"
40 depends on I2C && MACH_DAVINCI_DM355_EVM 48 depends on I2C && MACH_DAVINCI_DM355_EVM
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f3b277b90d40..d9522943d2fb 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -4,6 +4,7 @@
4 4
5obj-$(CONFIG_MFD_SM501) += sm501.o 5obj-$(CONFIG_MFD_SM501) += sm501.o
6obj-$(CONFIG_MFD_ASIC3) += asic3.o 6obj-$(CONFIG_MFD_ASIC3) += asic3.o
7obj-$(CONFIG_MFD_SH_MOBILE_SDHI) += sh_mobile_sdhi.o
7 8
8obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o 9obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
9obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o 10obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c
new file mode 100644
index 000000000000..56f72cc1d569
--- /dev/null
+++ b/drivers/mfd/sh_mobile_sdhi.c
@@ -0,0 +1,145 @@
1/*
2 * SuperH Mobile SDHI
3 *
4 * Copyright (C) 2009 Magnus Damm
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Based on "Compaq ASIC3 support":
11 *
12 * Copyright 2001 Compaq Computer Corporation.
13 * Copyright 2004-2005 Phil Blundell
14 * Copyright 2007-2008 OpenedHand Ltd.
15 *
16 * Authors: Phil Blundell <pb@handhelds.org>,
17 * Samuel Ortiz <sameo@openedhand.com>
18 *
19 */
20
21#include <linux/kernel.h>
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24
25#include <linux/mfd/core.h>
26#include <linux/mfd/tmio.h>
27
28struct sh_mobile_sdhi {
29 struct clk *clk;
30 struct tmio_mmc_data mmc_data;
31 struct mfd_cell cell_mmc;
32};
33
34static struct resource sh_mobile_sdhi_resources[] = {
35 {
36 .start = 0x000,
37 .end = 0x1ff,
38 .flags = IORESOURCE_MEM,
39 },
40 {
41 .start = 0,
42 .end = 0,
43 .flags = IORESOURCE_IRQ,
44 },
45};
46
47static struct mfd_cell sh_mobile_sdhi_cell = {
48 .name = "tmio-mmc",
49 .num_resources = ARRAY_SIZE(sh_mobile_sdhi_resources),
50 .resources = sh_mobile_sdhi_resources,
51};
52
53static int __init sh_mobile_sdhi_probe(struct platform_device *pdev)
54{
55 struct sh_mobile_sdhi *priv;
56 struct resource *mem;
57 char clk_name[8];
58 int ret, irq;
59
60 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
61 if (!mem)
62 dev_err(&pdev->dev, "missing MEM resource\n");
63
64 irq = platform_get_irq(pdev, 0);
65 if (irq < 0)
66 dev_err(&pdev->dev, "missing IRQ resource\n");
67
68 if (!mem || (irq < 0))
69 return -EINVAL;
70
71 priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL);
72 if (priv == NULL) {
73 dev_err(&pdev->dev, "kzalloc failed\n");
74 return -ENOMEM;
75 }
76
77 snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
78 priv->clk = clk_get(&pdev->dev, clk_name);
79 if (IS_ERR(priv->clk)) {
80 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
81 ret = PTR_ERR(priv->clk);
82 kfree(priv);
83 return ret;
84 }
85
86 clk_enable(priv->clk);
87
88 /* FIXME: silly const unsigned int hclk */
89 *(unsigned int *)&priv->mmc_data.hclk = clk_get_rate(priv->clk);
90
91 memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
92 priv->cell_mmc.driver_data = &priv->mmc_data;
93 priv->cell_mmc.platform_data = &priv->cell_mmc;
94 priv->cell_mmc.data_size = sizeof(priv->cell_mmc);
95
96 platform_set_drvdata(pdev, priv);
97
98 ret = mfd_add_devices(&pdev->dev, pdev->id,
99 &priv->cell_mmc, 1, mem, irq);
100 if (ret) {
101 clk_disable(priv->clk);
102 clk_put(priv->clk);
103 kfree(priv);
104 }
105
106 return ret;
107}
108
109static int sh_mobile_sdhi_remove(struct platform_device *pdev)
110{
111 struct sh_mobile_sdhi *priv = platform_get_drvdata(pdev);
112
113 mfd_remove_devices(&pdev->dev);
114 clk_disable(priv->clk);
115 clk_put(priv->clk);
116 kfree(priv);
117
118 return 0;
119}
120
121static struct platform_driver sh_mobile_sdhi_driver = {
122 .driver = {
123 .name = "sh_mobile_sdhi",
124 .owner = THIS_MODULE,
125 },
126 .probe = sh_mobile_sdhi_probe,
127 .remove = __devexit_p(sh_mobile_sdhi_remove),
128};
129
130static int __init sh_mobile_sdhi_init(void)
131{
132 return platform_driver_register(&sh_mobile_sdhi_driver);
133}
134
135static void __exit sh_mobile_sdhi_exit(void)
136{
137 platform_driver_unregister(&sh_mobile_sdhi_driver);
138}
139
140module_init(sh_mobile_sdhi_init);
141module_exit(sh_mobile_sdhi_exit);
142
143MODULE_DESCRIPTION("SuperH Mobile SDHI driver");
144MODULE_AUTHOR("Magnus Damm");
145MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 432ae8358c86..e04b751680d0 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -329,7 +329,7 @@ config MMC_SDRICOH_CS
329 329
330config MMC_TMIO 330config MMC_TMIO
331 tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support" 331 tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
332 depends on MFD_TMIO || MFD_ASIC3 332 depends on MFD_TMIO || MFD_ASIC3 || SUPERH
333 help 333 help
334 This provides support for the SD/MMC cell found in TC6393XB, 334 This provides support for the SD/MMC cell found in TC6393XB,
335 T7L66XB and also HTC ASIC3 335 T7L66XB and also HTC ASIC3
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 559b5fe9dc0f..a7e5c2e9986c 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -2,6 +2,7 @@
2 * Shared interrupt handling code for IPR and INTC2 types of IRQs. 2 * Shared interrupt handling code for IPR and INTC2 types of IRQs.
3 * 3 *
4 * Copyright (C) 2007, 2008 Magnus Damm 4 * Copyright (C) 2007, 2008 Magnus Damm
5 * Copyright (C) 2009 Paul Mundt
5 * 6 *
6 * Based on intc2.c and ipr.c 7 * Based on intc2.c and ipr.c
7 * 8 *
@@ -24,6 +25,7 @@
24#include <linux/sysdev.h> 25#include <linux/sysdev.h>
25#include <linux/list.h> 26#include <linux/list.h>
26#include <linux/topology.h> 27#include <linux/topology.h>
28#include <linux/bitmap.h>
27 29
28#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ 30#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
29 ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ 31 ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
@@ -59,6 +61,20 @@ struct intc_desc_int {
59 61
60static LIST_HEAD(intc_list); 62static LIST_HEAD(intc_list);
61 63
64/*
65 * The intc_irq_map provides a global map of bound IRQ vectors for a
66 * given platform. Allocation of IRQs are either static through the CPU
67 * vector map, or dynamic in the case of board mux vectors or MSI.
68 *
69 * As this is a central point for all IRQ controllers on the system,
70 * each of the available sources are mapped out here. This combined with
71 * sparseirq makes it quite trivial to keep the vector map tightly packed
72 * when dynamically creating IRQs, as well as tying in to otherwise
73 * unused irq_desc positions in the sparse array.
74 */
75static DECLARE_BITMAP(intc_irq_map, NR_IRQS);
76static DEFINE_SPINLOCK(vector_lock);
77
62#ifdef CONFIG_SMP 78#ifdef CONFIG_SMP
63#define IS_SMP(x) x.smp 79#define IS_SMP(x) x.smp
64#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c)) 80#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
@@ -70,9 +86,7 @@ static LIST_HEAD(intc_list);
70#endif 86#endif
71 87
72static unsigned int intc_prio_level[NR_IRQS]; /* for now */ 88static unsigned int intc_prio_level[NR_IRQS]; /* for now */
73#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
74static unsigned long ack_handle[NR_IRQS]; 89static unsigned long ack_handle[NR_IRQS];
75#endif
76 90
77static inline struct intc_desc_int *get_intc_desc(unsigned int irq) 91static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
78{ 92{
@@ -250,7 +264,6 @@ static int intc_set_wake(unsigned int irq, unsigned int on)
250 return 0; /* allow wakeup, but setup hardware in intc_suspend() */ 264 return 0; /* allow wakeup, but setup hardware in intc_suspend() */
251} 265}
252 266
253#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
254static void intc_mask_ack(unsigned int irq) 267static void intc_mask_ack(unsigned int irq)
255{ 268{
256 struct intc_desc_int *d = get_intc_desc(irq); 269 struct intc_desc_int *d = get_intc_desc(irq);
@@ -282,7 +295,6 @@ static void intc_mask_ack(unsigned int irq)
282 } 295 }
283 } 296 }
284} 297}
285#endif
286 298
287static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, 299static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
288 unsigned int nr_hp, 300 unsigned int nr_hp,
@@ -501,7 +513,6 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc,
501 return 0; 513 return 0;
502} 514}
503 515
504#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
505static unsigned int __init intc_ack_data(struct intc_desc *desc, 516static unsigned int __init intc_ack_data(struct intc_desc *desc,
506 struct intc_desc_int *d, 517 struct intc_desc_int *d,
507 intc_enum enum_id) 518 intc_enum enum_id)
@@ -533,7 +544,6 @@ static unsigned int __init intc_ack_data(struct intc_desc *desc,
533 544
534 return 0; 545 return 0;
535} 546}
536#endif
537 547
538static unsigned int __init intc_sense_data(struct intc_desc *desc, 548static unsigned int __init intc_sense_data(struct intc_desc *desc,
539 struct intc_desc_int *d, 549 struct intc_desc_int *d,
@@ -572,6 +582,11 @@ static void __init intc_register_irq(struct intc_desc *desc,
572 struct intc_handle_int *hp; 582 struct intc_handle_int *hp;
573 unsigned int data[2], primary; 583 unsigned int data[2], primary;
574 584
585 /*
586 * Register the IRQ position with the global IRQ map
587 */
588 set_bit(irq, intc_irq_map);
589
575 /* Prefer single interrupt source bitmap over other combinations: 590 /* Prefer single interrupt source bitmap over other combinations:
576 * 1. bitmap, single interrupt source 591 * 1. bitmap, single interrupt source
577 * 2. priority, single interrupt source 592 * 2. priority, single interrupt source
@@ -641,10 +656,8 @@ static void __init intc_register_irq(struct intc_desc *desc,
641 /* irq should be disabled by default */ 656 /* irq should be disabled by default */
642 d->chip.mask(irq); 657 d->chip.mask(irq);
643 658
644#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
645 if (desc->ack_regs) 659 if (desc->ack_regs)
646 ack_handle[irq] = intc_ack_data(desc, d, enum_id); 660 ack_handle[irq] = intc_ack_data(desc, d, enum_id);
647#endif
648} 661}
649 662
650static unsigned int __init save_reg(struct intc_desc_int *d, 663static unsigned int __init save_reg(struct intc_desc_int *d,
@@ -681,10 +694,8 @@ void __init register_intc_controller(struct intc_desc *desc)
681 d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0; 694 d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0;
682 d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0; 695 d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
683 d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0; 696 d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
684
685#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
686 d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0; 697 d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0;
687#endif 698
688 d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT); 699 d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT);
689#ifdef CONFIG_SMP 700#ifdef CONFIG_SMP
690 d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT); 701 d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT);
@@ -727,14 +738,12 @@ void __init register_intc_controller(struct intc_desc *desc)
727 d->chip.set_type = intc_set_sense; 738 d->chip.set_type = intc_set_sense;
728 d->chip.set_wake = intc_set_wake; 739 d->chip.set_wake = intc_set_wake;
729 740
730#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
731 if (desc->ack_regs) { 741 if (desc->ack_regs) {
732 for (i = 0; i < desc->nr_ack_regs; i++) 742 for (i = 0; i < desc->nr_ack_regs; i++)
733 k += save_reg(d, k, desc->ack_regs[i].set_reg, 0); 743 k += save_reg(d, k, desc->ack_regs[i].set_reg, 0);
734 744
735 d->chip.mask_ack = intc_mask_ack; 745 d->chip.mask_ack = intc_mask_ack;
736 } 746 }
737#endif
738 747
739 BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ 748 BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
740 749
@@ -856,5 +865,91 @@ static int __init register_intc_sysdevs(void)
856 865
857 return error; 866 return error;
858} 867}
859
860device_initcall(register_intc_sysdevs); 868device_initcall(register_intc_sysdevs);
869
870/*
871 * Dynamic IRQ allocation and deallocation
872 */
873static unsigned int create_irq_on_node(unsigned int irq_want, int node)
874{
875 unsigned int irq = 0, new;
876 unsigned long flags;
877 struct irq_desc *desc;
878
879 spin_lock_irqsave(&vector_lock, flags);
880
881 /*
882 * First try the wanted IRQ, then scan.
883 */
884 if (test_and_set_bit(irq_want, intc_irq_map)) {
885 new = find_first_zero_bit(intc_irq_map, nr_irqs);
886 if (unlikely(new == nr_irqs))
887 goto out_unlock;
888
889 desc = irq_to_desc_alloc_node(new, node);
890 if (unlikely(!desc)) {
891 pr_info("can't get irq_desc for %d\n", new);
892 goto out_unlock;
893 }
894
895 desc = move_irq_desc(desc, node);
896 __set_bit(new, intc_irq_map);
897 irq = new;
898 }
899
900out_unlock:
901 spin_unlock_irqrestore(&vector_lock, flags);
902
903 if (irq > 0)
904 dynamic_irq_init(irq);
905
906 return irq;
907}
908
909int create_irq(void)
910{
911 int nid = cpu_to_node(smp_processor_id());
912 int irq;
913
914 irq = create_irq_on_node(NR_IRQS_LEGACY, nid);
915 if (irq == 0)
916 irq = -1;
917
918 return irq;
919}
920
921void destroy_irq(unsigned int irq)
922{
923 unsigned long flags;
924
925 dynamic_irq_cleanup(irq);
926
927 spin_lock_irqsave(&vector_lock, flags);
928 __clear_bit(irq, intc_irq_map);
929 spin_unlock_irqrestore(&vector_lock, flags);
930}
931
932int reserve_irq_vector(unsigned int irq)
933{
934 unsigned long flags;
935 int ret = 0;
936
937 spin_lock_irqsave(&vector_lock, flags);
938 if (test_and_set_bit(irq, intc_irq_map))
939 ret = -EBUSY;
940 spin_unlock_irqrestore(&vector_lock, flags);
941
942 return ret;
943}
944
945void reserve_irq_legacy(void)
946{
947 unsigned long flags;
948 int i, j;
949
950 spin_lock_irqsave(&vector_lock, flags);
951 j = find_first_bit(intc_irq_map, nr_irqs);
952 for (i = 0; i < j; i++)
953 __set_bit(i, intc_irq_map);
954 spin_unlock_irqrestore(&vector_lock, flags);
955}
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index 93c20e135ee1..4e8f57d4131f 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -106,7 +106,7 @@ static void maple_dma_reset(void)
106 * max delay is 11 106 * max delay is 11
107 */ 107 */
108 ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(0xFFFF), MAPLE_SPEED); 108 ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(0xFFFF), MAPLE_SPEED);
109 ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR); 109 ctrl_outl(virt_to_phys(maple_sendbuf), MAPLE_DMAADDR);
110 ctrl_outl(1, MAPLE_ENABLE); 110 ctrl_outl(1, MAPLE_ENABLE);
111} 111}
112 112
@@ -258,7 +258,7 @@ static void maple_build_block(struct mapleq *mq)
258 maple_lastptr = maple_sendptr; 258 maple_lastptr = maple_sendptr;
259 259
260 *maple_sendptr++ = (port << 16) | len | 0x80000000; 260 *maple_sendptr++ = (port << 16) | len | 0x80000000;
261 *maple_sendptr++ = PHYSADDR(mq->recvbuf->buf); 261 *maple_sendptr++ = virt_to_phys(mq->recvbuf->buf);
262 *maple_sendptr++ = 262 *maple_sendptr++ =
263 mq->command | (to << 8) | (from << 16) | (len << 24); 263 mq->command | (to << 8) | (from << 16) | (len << 24);
264 while (len-- > 0) 264 while (len-- > 0)
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 3ad5157f9899..b4b5de930cf5 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -281,18 +281,34 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
281 struct list_head *pagelist) 281 struct list_head *pagelist)
282{ 282{
283 struct sh_mobile_lcdc_chan *ch = info->par; 283 struct sh_mobile_lcdc_chan *ch = info->par;
284 unsigned int nr_pages;
285 284
286 /* enable clocks before accessing hardware */ 285 /* enable clocks before accessing hardware */
287 sh_mobile_lcdc_clk_on(ch->lcdc); 286 sh_mobile_lcdc_clk_on(ch->lcdc);
288 287
289 nr_pages = sh_mobile_lcdc_sginit(info, pagelist); 288 /*
290 dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 289 * It's possible to get here without anything on the pagelist via
291 290 * sh_mobile_lcdc_deferred_io_touch() or via a userspace fsync()
292 /* trigger panel update */ 291 * invocation. In the former case, the acceleration routines are
293 lcdc_write_chan(ch, LDSM2R, 1); 292 * stepped in to when using the framebuffer console causing the
294 293 * workqueue to be scheduled without any dirty pages on the list.
295 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 294 *
295 * Despite this, a panel update is still needed given that the
296 * acceleration routines have their own methods for writing in
297 * that still need to be updated.
298 *
299 * The fsync() and empty pagelist case could be optimized for,
300 * but we don't bother, as any application exhibiting such
301 * behaviour is fundamentally broken anyways.
302 */
303 if (!list_empty(pagelist)) {
304 unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
305
306 /* trigger panel update */
307 dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
308 lcdc_write_chan(ch, LDSM2R, 1);
309 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
310 } else
311 lcdc_write_chan(ch, LDSM2R, 1);
296} 312}
297 313
298static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) 314static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)