aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS3
-rw-r--r--arch/arm/mach-shmobile/Kconfig26
-rw-r--r--arch/arm/mach-shmobile/Makefile6
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c817
-rw-r--r--arch/arm/mach-shmobile/board-g3evm.c59
-rw-r--r--arch/arm/mach-shmobile/board-g4evm.c153
-rw-r--r--arch/arm/mach-shmobile/clock-sh7367.c357
-rw-r--r--arch/arm/mach-shmobile/clock-sh7372.c560
-rw-r--r--arch/arm/mach-shmobile/clock-sh7377.c369
-rw-r--r--arch/arm/mach-shmobile/clock.c44
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h10
-rw-r--r--arch/arm/mach-shmobile/include/mach/irqs.h6
-rw-r--r--arch/arm/mach-shmobile/include/mach/memory.h3
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h30
-rw-r--r--arch/arm/mach-shmobile/include/mach/vmalloc.h3
-rw-r--r--arch/arm/mach-shmobile/intc-sh7367.c178
-rw-r--r--arch/arm/mach-shmobile/intc-sh7372.c232
-rw-r--r--arch/arm/mach-shmobile/intc-sh7377.c300
-rw-r--r--arch/arm/mach-shmobile/pfc-sh7372.c3
-rw-r--r--arch/arm/mach-shmobile/setup-sh7367.c30
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c391
-rw-r--r--arch/arm/mach-shmobile/setup-sh7377.c34
-rw-r--r--arch/sh/boards/mach-ap325rxa/setup.c2
-rw-r--r--arch/sh/boards/mach-kfr2r09/Makefile6
-rw-r--r--arch/sh/boards/mach-kfr2r09/lcd_wqvga.c2
-rw-r--r--arch/sh/include/mach-kfr2r09/mach/kfr2r09.h16
-rw-r--r--drivers/dma/Kconfig2
-rw-r--r--drivers/dma/shdma.c8
-rw-r--r--drivers/i2c/busses/Kconfig2
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c121
-rw-r--r--drivers/net/irda/sh_irda.c6
-rw-r--r--drivers/serial/sh-sci.c42
-rw-r--r--drivers/serial/sh-sci.h29
-rw-r--r--drivers/sh/Makefile5
-rw-r--r--drivers/sh/clk-cpg.c58
-rw-r--r--drivers/video/Kconfig15
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/sh_mipi_dsi.c505
-rw-r--r--drivers/video/sh_mobile_hdmi.c1028
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c196
-rw-r--r--include/linux/serial_core.h3
-rw-r--r--include/linux/sh_clk.h23
-rw-r--r--include/video/mipi_display.h130
-rw-r--r--include/video/sh_mipi_dsi.h35
-rw-r--r--include/video/sh_mobile_hdmi.h22
-rw-r--r--include/video/sh_mobile_lcdc.h41
46 files changed, 5602 insertions, 311 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 5fb38d3f142..0c0d829176a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -955,8 +955,9 @@ ARM/SHMOBILE ARM ARCHITECTURE
955M: Paul Mundt <lethal@linux-sh.org> 955M: Paul Mundt <lethal@linux-sh.org>
956M: Magnus Damm <magnus.damm@gmail.com> 956M: Magnus Damm <magnus.damm@gmail.com>
957L: linux-sh@vger.kernel.org 957L: linux-sh@vger.kernel.org
958T: git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/genesis-2.6.git
959W: http://oss.renesas.com 958W: http://oss.renesas.com
959Q: http://patchwork.kernel.org/project/linux-sh/list/
960T: git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/genesis-2.6.git
960S: Supported 961S: Supported
961F: arch/arm/mach-shmobile/ 962F: arch/arm/mach-shmobile/
962F: drivers/sh/ 963F: drivers/sh/
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 4c704b4e8b3..54b479c35ee 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -7,6 +7,7 @@ config ARCH_SH7367
7 select CPU_V6 7 select CPU_V6
8 select HAVE_CLK 8 select HAVE_CLK
9 select COMMON_CLKDEV 9 select COMMON_CLKDEV
10 select SH_CLK_CPG
10 select GENERIC_CLOCKEVENTS 11 select GENERIC_CLOCKEVENTS
11 12
12config ARCH_SH7377 13config ARCH_SH7377
@@ -14,6 +15,7 @@ config ARCH_SH7377
14 select CPU_V7 15 select CPU_V7
15 select HAVE_CLK 16 select HAVE_CLK
16 select COMMON_CLKDEV 17 select COMMON_CLKDEV
18 select SH_CLK_CPG
17 select GENERIC_CLOCKEVENTS 19 select GENERIC_CLOCKEVENTS
18 20
19config ARCH_SH7372 21config ARCH_SH7372
@@ -21,6 +23,7 @@ config ARCH_SH7372
21 select CPU_V7 23 select CPU_V7
22 select HAVE_CLK 24 select HAVE_CLK
23 select COMMON_CLKDEV 25 select COMMON_CLKDEV
26 select SH_CLK_CPG
24 select GENERIC_CLOCKEVENTS 27 select GENERIC_CLOCKEVENTS
25 28
26comment "SH-Mobile Board Type" 29comment "SH-Mobile Board Type"
@@ -39,6 +42,20 @@ config MACH_AP4EVB
39 bool "AP4EVB board" 42 bool "AP4EVB board"
40 depends on ARCH_SH7372 43 depends on ARCH_SH7372
41 select ARCH_REQUIRE_GPIOLIB 44 select ARCH_REQUIRE_GPIOLIB
45 select SH_LCD_MIPI_DSI
46
47choice
48 prompt "AP4EVB LCD panel selection"
49 default AP4EVB_QHD
50 depends on MACH_AP4EVB
51
52config AP4EVB_QHD
53 bool "MIPI-DSI QHD (960x540)"
54
55config AP4EVB_WVGA
56 bool "Parallel WVGA (800x480)"
57
58endchoice
42 59
43comment "SH-Mobile System Configuration" 60comment "SH-Mobile System Configuration"
44 61
@@ -88,6 +105,15 @@ config SH_TIMER_CMT
88 help 105 help
89 This enables build of the CMT timer driver. 106 This enables build of the CMT timer driver.
90 107
108config SH_TIMER_TMU
109 bool "TMU timer driver"
110 default y
111 help
112 This enables build of the TMU timer driver.
113
91endmenu 114endmenu
92 115
116config SH_CLK_CPG
117 bool
118
93endif 119endif
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 6d385d371c3..5e16b4c6922 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -3,12 +3,12 @@
3# 3#
4 4
5# Common objects 5# Common objects
6obj-y := timer.o console.o 6obj-y := timer.o console.o clock.o
7 7
8# CPU objects 8# CPU objects
9obj-$(CONFIG_ARCH_SH7367) += setup-sh7367.o clock-sh7367.o intc-sh7367.o 9obj-$(CONFIG_ARCH_SH7367) += setup-sh7367.o clock-sh7367.o intc-sh7367.o
10obj-$(CONFIG_ARCH_SH7377) += setup-sh7377.o clock-sh7367.o intc-sh7377.o 10obj-$(CONFIG_ARCH_SH7377) += setup-sh7377.o clock-sh7377.o intc-sh7377.o
11obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7367.o intc-sh7372.o 11obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o
12 12
13# Pinmux setup 13# Pinmux setup
14pfc-$(CONFIG_ARCH_SH7367) := pfc-sh7367.o 14pfc-$(CONFIG_ARCH_SH7367) := pfc-sh7367.o
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 1c2ec96ce26..23d472f9525 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -17,25 +17,45 @@
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */ 19 */
20#include <linux/clk.h>
20#include <linux/kernel.h> 21#include <linux/kernel.h>
21#include <linux/init.h> 22#include <linux/init.h>
22#include <linux/interrupt.h> 23#include <linux/interrupt.h>
23#include <linux/irq.h> 24#include <linux/irq.h>
24#include <linux/platform_device.h> 25#include <linux/platform_device.h>
25#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/mfd/sh_mobile_sdhi.h>
28#include <linux/mmc/host.h>
26#include <linux/mtd/mtd.h> 29#include <linux/mtd/mtd.h>
27#include <linux/mtd/partitions.h> 30#include <linux/mtd/partitions.h>
28#include <linux/mtd/physmap.h> 31#include <linux/mtd/physmap.h>
32#include <linux/mmc/host.h>
33#include <linux/mmc/sh_mmcif.h>
34#include <linux/i2c.h>
35#include <linux/i2c/tsc2007.h>
29#include <linux/io.h> 36#include <linux/io.h>
30#include <linux/smsc911x.h> 37#include <linux/smsc911x.h>
38#include <linux/sh_intc.h>
39#include <linux/sh_clk.h>
31#include <linux/gpio.h> 40#include <linux/gpio.h>
32#include <linux/input.h> 41#include <linux/input.h>
33#include <linux/input/sh_keysc.h> 42#include <linux/input/sh_keysc.h>
43#include <linux/usb/r8a66597.h>
44
45#include <sound/sh_fsi.h>
46
47#include <video/sh_mobile_hdmi.h>
48#include <video/sh_mobile_lcdc.h>
49#include <video/sh_mipi_dsi.h>
50
34#include <mach/common.h> 51#include <mach/common.h>
52#include <mach/irqs.h>
35#include <mach/sh7372.h> 53#include <mach/sh7372.h>
54
36#include <asm/mach-types.h> 55#include <asm/mach-types.h>
37#include <asm/mach/arch.h> 56#include <asm/mach/arch.h>
38#include <asm/mach/map.h> 57#include <asm/mach/map.h>
58#include <asm/mach/time.h>
39 59
40/* 60/*
41 * Address Interface BusWidth note 61 * Address Interface BusWidth note
@@ -80,12 +100,56 @@
80 */ 100 */
81 101
82/* 102/*
83 * KEYSC 103 * LCD / IRQ / KEYSC / IrDA
104 *
105 * IRQ = IRQ26 (TS), IRQ27 (VIO), IRQ28 (QHD-TouchScreen)
106 * LCD = 2nd LCDC (WVGA)
84 * 107 *
85 * SW43 KEYSC 108 * | SW43 |
86 * ------------------------- 109 * SW3 | ON | OFF |
87 * ON enable 110 * -------------+-----------------------+---------------+
88 * OFF disable 111 * ON | KEY / IrDA | LCD |
112 * OFF | KEY / IrDA / IRQ | IRQ |
113 *
114 *
115 * QHD / WVGA display
116 *
117 * You can choice display type on menuconfig.
118 * Then, check above dip-switch.
119 */
120
121/*
122 * USB
123 *
124 * J7 : 1-2 MAX3355E VBUS
125 * 2-3 DC 5.0V
126 *
127 * S39: bit2: off
128 */
129
130/*
131 * FSI/FSMI
132 *
133 * SW41 : ON : SH-Mobile AP4 Audio Mode
134 * : OFF : Bluetooth Audio Mode
135 */
136
137/*
138 * MMC0/SDHI1 (CN7)
139 *
140 * J22 : select card voltage
141 * 1-2 pin : 1.8v
142 * 2-3 pin : 3.3v
143 *
144 * SW1 | SW33
145 * | bit1 | bit2 | bit3 | bit4
146 * ------------+------+------+------+-------
147 * MMC0 OFF | OFF | ON | ON | X
148 * SDHI1 OFF | ON | X | OFF | ON
149 *
150 * voltage lebel
151 * CN7 : 1.8v
152 * CN12: 3.3v
89 */ 153 */
90 154
91/* MTD */ 155/* MTD */
@@ -148,7 +212,7 @@ static struct resource smc911x_resources[] = {
148 .end = 0x16000000 - 1, 212 .end = 0x16000000 - 1,
149 .flags = IORESOURCE_MEM, 213 .flags = IORESOURCE_MEM,
150 }, { 214 }, {
151 .start = 6, 215 .start = evt2irq(0x02c0) /* IRQ6A */,
152 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, 216 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
153 }, 217 },
154}; 218};
@@ -169,6 +233,180 @@ static struct platform_device smc911x_device = {
169 }, 233 },
170}; 234};
171 235
236/* SH_MMCIF */
237static struct resource sh_mmcif_resources[] = {
238 [0] = {
239 .name = "SH_MMCIF",
240 .start = 0xE6BD0000,
241 .end = 0xE6BD00FF,
242 .flags = IORESOURCE_MEM,
243 },
244 [1] = {
245 /* MMC ERR */
246 .start = evt2irq(0x1ac0),
247 .flags = IORESOURCE_IRQ,
248 },
249 [2] = {
250 /* MMC NOR */
251 .start = evt2irq(0x1ae0),
252 .flags = IORESOURCE_IRQ,
253 },
254};
255
256static struct sh_mmcif_plat_data sh_mmcif_plat = {
257 .sup_pclk = 0,
258 .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
259 .caps = MMC_CAP_4_BIT_DATA |
260 MMC_CAP_8_BIT_DATA |
261 MMC_CAP_NEEDS_POLL,
262};
263
264static struct platform_device sh_mmcif_device = {
265 .name = "sh_mmcif",
266 .id = 0,
267 .dev = {
268 .dma_mask = NULL,
269 .coherent_dma_mask = 0xffffffff,
270 .platform_data = &sh_mmcif_plat,
271 },
272 .num_resources = ARRAY_SIZE(sh_mmcif_resources),
273 .resource = sh_mmcif_resources,
274};
275
276/* SDHI0 */
277static struct sh_mobile_sdhi_info sdhi0_info = {
278 .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
279 .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
280};
281
282static struct resource sdhi0_resources[] = {
283 [0] = {
284 .name = "SDHI0",
285 .start = 0xe6850000,
286 .end = 0xe68501ff,
287 .flags = IORESOURCE_MEM,
288 },
289 [1] = {
290 .start = evt2irq(0x0e00) /* SDHI0 */,
291 .flags = IORESOURCE_IRQ,
292 },
293};
294
295static struct platform_device sdhi0_device = {
296 .name = "sh_mobile_sdhi",
297 .num_resources = ARRAY_SIZE(sdhi0_resources),
298 .resource = sdhi0_resources,
299 .id = 0,
300 .dev = {
301 .platform_data = &sdhi0_info,
302 },
303};
304
305/* SDHI1 */
306static struct sh_mobile_sdhi_info sdhi1_info = {
307 .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX,
308 .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX,
309 .tmio_ocr_mask = MMC_VDD_165_195,
310};
311
312static struct resource sdhi1_resources[] = {
313 [0] = {
314 .name = "SDHI1",
315 .start = 0xe6860000,
316 .end = 0xe68601ff,
317 .flags = IORESOURCE_MEM,
318 },
319 [1] = {
320 .start = evt2irq(0x0e80),
321 .flags = IORESOURCE_IRQ,
322 },
323};
324
325static struct platform_device sdhi1_device = {
326 .name = "sh_mobile_sdhi",
327 .num_resources = ARRAY_SIZE(sdhi1_resources),
328 .resource = sdhi1_resources,
329 .id = 1,
330 .dev = {
331 .platform_data = &sdhi1_info,
332 },
333};
334
335/* USB1 */
336static void usb1_host_port_power(int port, int power)
337{
338 if (!power) /* only power-on supported for now */
339 return;
340
341 /* set VBOUT/PWEN and EXTLP1 in DVSTCTR */
342 __raw_writew(__raw_readw(0xE68B0008) | 0x600, 0xE68B0008);
343}
344
345static struct r8a66597_platdata usb1_host_data = {
346 .on_chip = 1,
347 .port_power = usb1_host_port_power,
348};
349
350static struct resource usb1_host_resources[] = {
351 [0] = {
352 .name = "USBHS",
353 .start = 0xE68B0000,
354 .end = 0xE68B00E6 - 1,
355 .flags = IORESOURCE_MEM,
356 },
357 [1] = {
358 .start = evt2irq(0x1ce0) /* USB1_USB1I0 */,
359 .flags = IORESOURCE_IRQ,
360 },
361};
362
363static struct platform_device usb1_host_device = {
364 .name = "r8a66597_hcd",
365 .id = 1,
366 .dev = {
367 .dma_mask = NULL, /* not use dma */
368 .coherent_dma_mask = 0xffffffff,
369 .platform_data = &usb1_host_data,
370 },
371 .num_resources = ARRAY_SIZE(usb1_host_resources),
372 .resource = usb1_host_resources,
373};
374
375static struct sh_mobile_lcdc_info lcdc_info = {
376 .ch[0] = {
377 .chan = LCDC_CHAN_MAINLCD,
378 .bpp = 16,
379 }
380};
381
382static struct resource lcdc_resources[] = {
383 [0] = {
384 .name = "LCDC",
385 .start = 0xfe940000, /* P4-only space */
386 .end = 0xfe943fff,
387 .flags = IORESOURCE_MEM,
388 },
389 [1] = {
390 .start = intcs_evt2irq(0x580),
391 .flags = IORESOURCE_IRQ,
392 },
393};
394
395static struct platform_device lcdc_device = {
396 .name = "sh_mobile_lcdc_fb",
397 .num_resources = ARRAY_SIZE(lcdc_resources),
398 .resource = lcdc_resources,
399 .dev = {
400 .platform_data = &lcdc_info,
401 .coherent_dma_mask = ~0,
402 },
403};
404
405/*
406 * QHD display
407 */
408#ifdef CONFIG_AP4EVB_QHD
409
172/* KEYSC (Needs SW43 set to ON) */ 410/* KEYSC (Needs SW43 set to ON) */
173static struct sh_keysc_info keysc_info = { 411static struct sh_keysc_info keysc_info = {
174 .mode = SH_KEYSC_MODE_1, 412 .mode = SH_KEYSC_MODE_1,
@@ -191,7 +429,7 @@ static struct resource keysc_resources[] = {
191 .flags = IORESOURCE_MEM, 429 .flags = IORESOURCE_MEM,
192 }, 430 },
193 [1] = { 431 [1] = {
194 .start = 79, 432 .start = evt2irq(0x0be0), /* KEYSC_KEY */
195 .flags = IORESOURCE_IRQ, 433 .flags = IORESOURCE_IRQ,
196 }, 434 },
197}; 435};
@@ -206,32 +444,362 @@ static struct platform_device keysc_device = {
206 }, 444 },
207}; 445};
208 446
209/* SDHI0 */ 447/* MIPI-DSI */
210static struct resource sdhi0_resources[] = { 448static struct resource mipidsi0_resources[] = {
211 [0] = { 449 [0] = {
212 .name = "SDHI0", 450 .start = 0xffc60000,
213 .start = 0xe6850000, 451 .end = 0xffc68fff,
214 .end = 0xe68501ff,
215 .flags = IORESOURCE_MEM, 452 .flags = IORESOURCE_MEM,
216 }, 453 },
454};
455
456static struct sh_mipi_dsi_info mipidsi0_info = {
457 .data_format = MIPI_RGB888,
458 .lcd_chan = &lcdc_info.ch[0],
459};
460
461static struct platform_device mipidsi0_device = {
462 .name = "sh-mipi-dsi",
463 .num_resources = ARRAY_SIZE(mipidsi0_resources),
464 .resource = mipidsi0_resources,
465 .id = 0,
466 .dev = {
467 .platform_data = &mipidsi0_info,
468 },
469};
470
471/* This function will disappear when we switch to (runtime) PM */
472static int __init ap4evb_init_display_clk(void)
473{
474 struct clk *lcdc_clk;
475 struct clk *dsitx_clk;
476 int ret;
477
478 lcdc_clk = clk_get(&lcdc_device.dev, "sh_mobile_lcdc_fb.0");
479 if (IS_ERR(lcdc_clk))
480 return PTR_ERR(lcdc_clk);
481
482 dsitx_clk = clk_get(&mipidsi0_device.dev, "sh-mipi-dsi.0");
483 if (IS_ERR(dsitx_clk)) {
484 ret = PTR_ERR(dsitx_clk);
485 goto eclkdsitxget;
486 }
487
488 ret = clk_enable(lcdc_clk);
489 if (ret < 0)
490 goto eclklcdcon;
491
492 ret = clk_enable(dsitx_clk);
493 if (ret < 0)
494 goto eclkdsitxon;
495
496 return 0;
497
498eclkdsitxon:
499 clk_disable(lcdc_clk);
500eclklcdcon:
501 clk_put(dsitx_clk);
502eclkdsitxget:
503 clk_put(lcdc_clk);
504
505 return ret;
506}
507device_initcall(ap4evb_init_display_clk);
508
509static struct platform_device *qhd_devices[] __initdata = {
510 &mipidsi0_device,
511 &keysc_device,
512};
513#endif /* CONFIG_AP4EVB_QHD */
514
515/* FSI */
516#define IRQ_FSI evt2irq(0x1840)
517#define FSIACKCR 0xE6150018
518static void fsiackcr_init(struct clk *clk)
519{
520 u32 status = __raw_readl(clk->enable_reg);
521
522 /* use external clock */
523 status &= ~0x000000ff;
524 status |= 0x00000080;
525 __raw_writel(status, clk->enable_reg);
526}
527
528static struct clk_ops fsiackcr_clk_ops = {
529 .init = fsiackcr_init,
530};
531
532static struct clk fsiackcr_clk = {
533 .ops = &fsiackcr_clk_ops,
534 .enable_reg = (void __iomem *)FSIACKCR,
535 .rate = 0, /* unknown */
536};
537
538static struct sh_fsi_platform_info fsi_info = {
539 .porta_flags = SH_FSI_BRS_INV |
540 SH_FSI_OUT_SLAVE_MODE |
541 SH_FSI_IN_SLAVE_MODE |
542 SH_FSI_OFMT(PCM) |
543 SH_FSI_IFMT(PCM),
544};
545
546static struct resource fsi_resources[] = {
547 [0] = {
548 .name = "FSI",
549 .start = 0xFE3C0000,
550 .end = 0xFE3C0400 - 1,
551 .flags = IORESOURCE_MEM,
552 },
217 [1] = { 553 [1] = {
218 .start = 96, 554 .start = IRQ_FSI,
219 .flags = IORESOURCE_IRQ, 555 .flags = IORESOURCE_IRQ,
220 }, 556 },
221}; 557};
222 558
223static struct platform_device sdhi0_device = { 559static struct platform_device fsi_device = {
224 .name = "sh_mobile_sdhi", 560 .name = "sh_fsi2",
225 .num_resources = ARRAY_SIZE(sdhi0_resources), 561 .id = 0,
226 .resource = sdhi0_resources, 562 .num_resources = ARRAY_SIZE(fsi_resources),
227 .id = 0, 563 .resource = fsi_resources,
564 .dev = {
565 .platform_data = &fsi_info,
566 },
567};
568
569static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
570 .clock_source = LCDC_CLK_EXTERNAL,
571 .ch[0] = {
572 .chan = LCDC_CHAN_MAINLCD,
573 .bpp = 16,
574 .interface_type = RGB24,
575 .clock_divider = 1,
576 .flags = LCDC_FLAGS_DWPOL,
577 .lcd_cfg = {
578 .name = "HDMI",
579 /* So far only 720p is supported */
580 .xres = 1280,
581 .yres = 720,
582 /*
583 * If left and right margins are not multiples of 8,
584 * LDHAJR will be adjusted accordingly by the LCDC
585 * driver. Until we start using EDID, these values
586 * might have to be adjusted for different monitors.
587 */
588 .left_margin = 200,
589 .right_margin = 88,
590 .hsync_len = 48,
591 .upper_margin = 20,
592 .lower_margin = 5,
593 .vsync_len = 5,
594 .pixclock = 13468,
595 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
596 },
597 }
598};
599
600static struct resource lcdc1_resources[] = {
601 [0] = {
602 .name = "LCDC1",
603 .start = 0xfe944000,
604 .end = 0xfe947fff,
605 .flags = IORESOURCE_MEM,
606 },
607 [1] = {
608 .start = intcs_evt2irq(0x17a0),
609 .flags = IORESOURCE_IRQ,
610 },
611};
612
613static struct platform_device lcdc1_device = {
614 .name = "sh_mobile_lcdc_fb",
615 .num_resources = ARRAY_SIZE(lcdc1_resources),
616 .resource = lcdc1_resources,
617 .id = 1,
618 .dev = {
619 .platform_data = &sh_mobile_lcdc1_info,
620 .coherent_dma_mask = ~0,
621 },
622};
623
624static struct sh_mobile_hdmi_info hdmi_info = {
625 .lcd_chan = &sh_mobile_lcdc1_info.ch[0],
626 .lcd_dev = &lcdc1_device.dev,
627};
628
629static struct resource hdmi_resources[] = {
630 [0] = {
631 .name = "HDMI",
632 .start = 0xe6be0000,
633 .end = 0xe6be00ff,
634 .flags = IORESOURCE_MEM,
635 },
636 [1] = {
637 /* There's also an HDMI interrupt on INTCS @ 0x18e0 */
638 .start = evt2irq(0x17e0),
639 .flags = IORESOURCE_IRQ,
640 },
641};
642
643static struct platform_device hdmi_device = {
644 .name = "sh-mobile-hdmi",
645 .num_resources = ARRAY_SIZE(hdmi_resources),
646 .resource = hdmi_resources,
647 .id = -1,
648 .dev = {
649 .platform_data = &hdmi_info,
650 },
228}; 651};
229 652
230static struct platform_device *ap4evb_devices[] __initdata = { 653static struct platform_device *ap4evb_devices[] __initdata = {
231 &nor_flash_device, 654 &nor_flash_device,
232 &smc911x_device, 655 &smc911x_device,
233 &keysc_device,
234 &sdhi0_device, 656 &sdhi0_device,
657 &sdhi1_device,
658 &usb1_host_device,
659 &fsi_device,
660 &sh_mmcif_device,
661 &lcdc1_device,
662 &lcdc_device,
663 &hdmi_device,
664};
665
666static int __init hdmi_init_pm_clock(void)
667{
668 struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
669 int ret;
670 long rate;
671
672 if (IS_ERR(hdmi_ick)) {
673 ret = PTR_ERR(hdmi_ick);
674 pr_err("Cannot get HDMI ICK: %d\n", ret);
675 goto out;
676 }
677
678 ret = clk_set_parent(&pllc2_clk, &dv_clki_div2_clk);
679 if (ret < 0) {
680 pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, pllc2_clk.usecount);
681 goto out;
682 }
683
684 pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&pllc2_clk));
685
686 rate = clk_round_rate(&pllc2_clk, 594000000);
687 if (rate < 0) {
688 pr_err("Cannot get suitable rate: %ld\n", rate);
689 ret = rate;
690 goto out;
691 }
692
693 ret = clk_set_rate(&pllc2_clk, rate);
694 if (ret < 0) {
695 pr_err("Cannot set rate %ld: %d\n", rate, ret);
696 goto out;
697 }
698
699 pr_debug("PLLC2 set frequency %lu\n", rate);
700
701 ret = clk_set_parent(hdmi_ick, &pllc2_clk);
702 if (ret < 0) {
703 pr_err("Cannot set HDMI parent: %d\n", ret);
704 goto out;
705 }
706
707out:
708 if (!IS_ERR(hdmi_ick))
709 clk_put(hdmi_ick);
710 return ret;
711}
712
713device_initcall(hdmi_init_pm_clock);
714
715/*
716 * FIXME !!
717 *
718 * gpio_no_direction
719 * gpio_pull_up
720 * are quick_hack.
721 *
722 * current gpio frame work doesn't have
723 * the method to control only pull up/down/free.
724 * this function should be replaced by correct gpio function
725 */
726static void __init gpio_no_direction(u32 addr)
727{
728 __raw_writeb(0x00, addr);
729}
730
731static void __init gpio_pull_up(u32 addr)
732{
733 u8 data = __raw_readb(addr);
734
735 data &= 0x0F;
736 data |= 0xC0;
737 __raw_writeb(data, addr);
738}
739
740/* TouchScreen */
741#define IRQ28 evt2irq(0x3380) /* IRQ28A */
742#define IRQ7 evt2irq(0x02e0) /* IRQ7A */
743static int ts_get_pendown_state(void)
744{
745 int val1, val2;
746
747 gpio_free(GPIO_FN_IRQ28_123);
748 gpio_free(GPIO_FN_IRQ7_40);
749
750 gpio_request(GPIO_PORT123, NULL);
751 gpio_request(GPIO_PORT40, NULL);
752
753 gpio_direction_input(GPIO_PORT123);
754 gpio_direction_input(GPIO_PORT40);
755
756 val1 = gpio_get_value(GPIO_PORT123);
757 val2 = gpio_get_value(GPIO_PORT40);
758
759 gpio_request(GPIO_FN_IRQ28_123, NULL); /* for QHD */
760 gpio_request(GPIO_FN_IRQ7_40, NULL); /* for WVGA */
761
762 return val1 ^ val2;
763}
764
765#define PORT40CR 0xE6051028
766#define PORT123CR 0xE605007B
767static int ts_init(void)
768{
769 gpio_request(GPIO_FN_IRQ28_123, NULL); /* for QHD */
770 gpio_request(GPIO_FN_IRQ7_40, NULL); /* for WVGA */
771
772 gpio_pull_up(PORT40CR);
773 gpio_pull_up(PORT123CR);
774
775 return 0;
776}
777
778static struct tsc2007_platform_data tsc2007_info = {
779 .model = 2007,
780 .x_plate_ohms = 180,
781 .get_pendown_state = ts_get_pendown_state,
782 .init_platform_hw = ts_init,
783};
784
785static struct i2c_board_info tsc_device = {
786 I2C_BOARD_INFO("tsc2007", 0x48),
787 .type = "tsc2007",
788 .platform_data = &tsc2007_info,
789 /*.irq is selected on ap4evb_init */
790};
791
792/* I2C */
793static struct i2c_board_info i2c0_devices[] = {
794 {
795 I2C_BOARD_INFO("ak4643", 0x13),
796 },
797};
798
799static struct i2c_board_info i2c1_devices[] = {
800 {
801 I2C_BOARD_INFO("r2025sd", 0x32),
802 },
235}; 803};
236 804
237static struct map_desc ap4evb_io_desc[] __initdata = { 805static struct map_desc ap4evb_io_desc[] __initdata = {
@@ -250,14 +818,18 @@ static void __init ap4evb_map_io(void)
250{ 818{
251 iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc)); 819 iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc));
252 820
253 /* setup early devices, clocks and console here as well */ 821 /* setup early devices and console here as well */
254 sh7372_add_early_devices(); 822 sh7372_add_early_devices();
255 sh7367_clock_init(); /* use g3 clocks for now */
256 shmobile_setup_console(); 823 shmobile_setup_console();
257} 824}
258 825
826#define GPIO_PORT9CR 0xE6051009
827#define GPIO_PORT10CR 0xE605100A
259static void __init ap4evb_init(void) 828static void __init ap4evb_init(void)
260{ 829{
830 u32 srcr4;
831 struct clk *clk;
832
261 sh7372_pinmux_init(); 833 sh7372_pinmux_init();
262 834
263 /* enable SCIFA0 */ 835 /* enable SCIFA0 */
@@ -296,6 +868,93 @@ static void __init ap4evb_init(void)
296 gpio_export(GPIO_PORT34, 0); 868 gpio_export(GPIO_PORT34, 0);
297 gpio_export(GPIO_PORT35, 0); 869 gpio_export(GPIO_PORT35, 0);
298 870
871 /* SDHI0 */
872 gpio_request(GPIO_FN_SDHICD0, NULL);
873 gpio_request(GPIO_FN_SDHIWP0, NULL);
874 gpio_request(GPIO_FN_SDHICMD0, NULL);
875 gpio_request(GPIO_FN_SDHICLK0, NULL);
876 gpio_request(GPIO_FN_SDHID0_3, NULL);
877 gpio_request(GPIO_FN_SDHID0_2, NULL);
878 gpio_request(GPIO_FN_SDHID0_1, NULL);
879 gpio_request(GPIO_FN_SDHID0_0, NULL);
880
881 /* SDHI1 */
882 gpio_request(GPIO_FN_SDHICMD1, NULL);
883 gpio_request(GPIO_FN_SDHICLK1, NULL);
884 gpio_request(GPIO_FN_SDHID1_3, NULL);
885 gpio_request(GPIO_FN_SDHID1_2, NULL);
886 gpio_request(GPIO_FN_SDHID1_1, NULL);
887 gpio_request(GPIO_FN_SDHID1_0, NULL);
888
889 /* MMCIF */
890 gpio_request(GPIO_FN_MMCD0_0, NULL);
891 gpio_request(GPIO_FN_MMCD0_1, NULL);
892 gpio_request(GPIO_FN_MMCD0_2, NULL);
893 gpio_request(GPIO_FN_MMCD0_3, NULL);
894 gpio_request(GPIO_FN_MMCD0_4, NULL);
895 gpio_request(GPIO_FN_MMCD0_5, NULL);
896 gpio_request(GPIO_FN_MMCD0_6, NULL);
897 gpio_request(GPIO_FN_MMCD0_7, NULL);
898 gpio_request(GPIO_FN_MMCCMD0, NULL);
899 gpio_request(GPIO_FN_MMCCLK0, NULL);
900
901 /* USB enable */
902 gpio_request(GPIO_FN_VBUS0_1, NULL);
903 gpio_request(GPIO_FN_IDIN_1_18, NULL);
904 gpio_request(GPIO_FN_PWEN_1_115, NULL);
905 gpio_request(GPIO_FN_OVCN_1_114, NULL);
906 gpio_request(GPIO_FN_EXTLP_1, NULL);
907 gpio_request(GPIO_FN_OVCN2_1, NULL);
908
909 /* setup USB phy */
910 __raw_writew(0x8a0a, 0xE6058130); /* USBCR2 */
911
912 /* enable FSI2 */
913 gpio_request(GPIO_FN_FSIAIBT, NULL);
914 gpio_request(GPIO_FN_FSIAILR, NULL);
915 gpio_request(GPIO_FN_FSIAISLD, NULL);
916 gpio_request(GPIO_FN_FSIAOSLD, NULL);
917 gpio_request(GPIO_PORT161, NULL);
918 gpio_direction_output(GPIO_PORT161, 0); /* slave */
919
920 gpio_request(GPIO_PORT9, NULL);
921 gpio_request(GPIO_PORT10, NULL);
922 gpio_no_direction(GPIO_PORT9CR); /* FSIAOBT needs no direction */
923 gpio_no_direction(GPIO_PORT10CR); /* FSIAOLR needs no direction */
924
925 /* set SPU2 clock to 119.6 MHz */
926 clk = clk_get(NULL, "spu_clk");
927 if (!IS_ERR(clk)) {
928 clk_set_rate(clk, clk_round_rate(clk, 119600000));
929 clk_put(clk);
930 }
931
932 /* change parent of FSI A */
933 clk = clk_get(NULL, "fsia_clk");
934 if (!IS_ERR(clk)) {
935 clk_register(&fsiackcr_clk);
936 clk_set_parent(clk, &fsiackcr_clk);
937 clk_put(clk);
938 }
939
940 /*
941 * set irq priority, to avoid sound chopping
942 * when NFS rootfs is used
943 * FSI(3) > SMSC911X(2)
944 */
945 intc_set_priority(IRQ_FSI, 3);
946
947 i2c_register_board_info(0, i2c0_devices,
948 ARRAY_SIZE(i2c0_devices));
949
950 i2c_register_board_info(1, i2c1_devices,
951 ARRAY_SIZE(i2c1_devices));
952
953#ifdef CONFIG_AP4EVB_QHD
954 /*
955 * QHD
956 */
957
299 /* enable KEYSC */ 958 /* enable KEYSC */
300 gpio_request(GPIO_FN_KEYOUT0, NULL); 959 gpio_request(GPIO_FN_KEYOUT0, NULL);
301 gpio_request(GPIO_FN_KEYOUT1, NULL); 960 gpio_request(GPIO_FN_KEYOUT1, NULL);
@@ -308,26 +967,122 @@ static void __init ap4evb_init(void)
308 gpio_request(GPIO_FN_KEYIN3_133, NULL); 967 gpio_request(GPIO_FN_KEYIN3_133, NULL);
309 gpio_request(GPIO_FN_KEYIN4, NULL); 968 gpio_request(GPIO_FN_KEYIN4, NULL);
310 969
311 /* SDHI0 */ 970 /* enable TouchScreen */
312 gpio_request(GPIO_FN_SDHICD0, NULL); 971 set_irq_type(IRQ28, IRQ_TYPE_LEVEL_LOW);
313 gpio_request(GPIO_FN_SDHIWP0, NULL); 972
314 gpio_request(GPIO_FN_SDHICMD0, NULL); 973 tsc_device.irq = IRQ28;
315 gpio_request(GPIO_FN_SDHICLK0, NULL); 974 i2c_register_board_info(1, &tsc_device, 1);
316 gpio_request(GPIO_FN_SDHID0_3, NULL); 975
317 gpio_request(GPIO_FN_SDHID0_2, NULL); 976 /* LCDC0 */
318 gpio_request(GPIO_FN_SDHID0_1, NULL); 977 lcdc_info.clock_source = LCDC_CLK_PERIPHERAL;
319 gpio_request(GPIO_FN_SDHID0_0, NULL); 978 lcdc_info.ch[0].interface_type = RGB24;
979 lcdc_info.ch[0].clock_divider = 1;
980 lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL;
981 lcdc_info.ch[0].lcd_cfg.name = "R63302(QHD)";
982 lcdc_info.ch[0].lcd_cfg.xres = 544;
983 lcdc_info.ch[0].lcd_cfg.yres = 961;
984 lcdc_info.ch[0].lcd_cfg.left_margin = 72;
985 lcdc_info.ch[0].lcd_cfg.right_margin = 600;
986 lcdc_info.ch[0].lcd_cfg.hsync_len = 16;
987 lcdc_info.ch[0].lcd_cfg.upper_margin = 8;
988 lcdc_info.ch[0].lcd_cfg.lower_margin = 8;
989 lcdc_info.ch[0].lcd_cfg.vsync_len = 2;
990 lcdc_info.ch[0].lcd_cfg.sync = FB_SYNC_VERT_HIGH_ACT |
991 FB_SYNC_HOR_HIGH_ACT;
992 lcdc_info.ch[0].lcd_size_cfg.width = 44;
993 lcdc_info.ch[0].lcd_size_cfg.height = 79;
994
995 platform_add_devices(qhd_devices, ARRAY_SIZE(qhd_devices));
996
997#else
998 /*
999 * WVGA
1000 */
1001 gpio_request(GPIO_FN_LCDD17, NULL);
1002 gpio_request(GPIO_FN_LCDD16, NULL);
1003 gpio_request(GPIO_FN_LCDD15, NULL);
1004 gpio_request(GPIO_FN_LCDD14, NULL);
1005 gpio_request(GPIO_FN_LCDD13, NULL);
1006 gpio_request(GPIO_FN_LCDD12, NULL);
1007 gpio_request(GPIO_FN_LCDD11, NULL);
1008 gpio_request(GPIO_FN_LCDD10, NULL);
1009 gpio_request(GPIO_FN_LCDD9, NULL);
1010 gpio_request(GPIO_FN_LCDD8, NULL);
1011 gpio_request(GPIO_FN_LCDD7, NULL);
1012 gpio_request(GPIO_FN_LCDD6, NULL);
1013 gpio_request(GPIO_FN_LCDD5, NULL);
1014 gpio_request(GPIO_FN_LCDD4, NULL);
1015 gpio_request(GPIO_FN_LCDD3, NULL);
1016 gpio_request(GPIO_FN_LCDD2, NULL);
1017 gpio_request(GPIO_FN_LCDD1, NULL);
1018 gpio_request(GPIO_FN_LCDD0, NULL);
1019 gpio_request(GPIO_FN_LCDDISP, NULL);
1020 gpio_request(GPIO_FN_LCDDCK, NULL);
1021
1022 gpio_request(GPIO_PORT189, NULL); /* backlight */
1023 gpio_direction_output(GPIO_PORT189, 1);
1024
1025 gpio_request(GPIO_PORT151, NULL); /* LCDDON */
1026 gpio_direction_output(GPIO_PORT151, 1);
1027
1028 lcdc_info.clock_source = LCDC_CLK_BUS;
1029 lcdc_info.ch[0].interface_type = RGB18;
1030 lcdc_info.ch[0].clock_divider = 2;
1031 lcdc_info.ch[0].flags = 0;
1032 lcdc_info.ch[0].lcd_cfg.name = "WVGA Panel";
1033 lcdc_info.ch[0].lcd_cfg.xres = 800;
1034 lcdc_info.ch[0].lcd_cfg.yres = 480;
1035 lcdc_info.ch[0].lcd_cfg.left_margin = 220;
1036 lcdc_info.ch[0].lcd_cfg.right_margin = 110;
1037 lcdc_info.ch[0].lcd_cfg.hsync_len = 70;
1038 lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
1039 lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
1040 lcdc_info.ch[0].lcd_cfg.vsync_len = 5;
1041 lcdc_info.ch[0].lcd_cfg.sync = 0;
1042 lcdc_info.ch[0].lcd_size_cfg.width = 152;
1043 lcdc_info.ch[0].lcd_size_cfg.height = 91;
1044
1045 /* enable TouchScreen */
1046 set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
1047
1048 tsc_device.irq = IRQ7;
1049 i2c_register_board_info(0, &tsc_device, 1);
1050#endif /* CONFIG_AP4EVB_QHD */
320 1051
321 sh7372_add_standard_devices(); 1052 sh7372_add_standard_devices();
322 1053
1054 /* HDMI */
1055 gpio_request(GPIO_FN_HDMI_HPD, NULL);
1056 gpio_request(GPIO_FN_HDMI_CEC, NULL);
1057
1058 /* Reset HDMI, must be held at least one EXTALR (32768Hz) period */
1059#define SRCR4 0xe61580bc
1060 srcr4 = __raw_readl(SRCR4);
1061 __raw_writel(srcr4 | (1 << 13), SRCR4);
1062 udelay(50);
1063 __raw_writel(srcr4 & ~(1 << 13), SRCR4);
1064
323 platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); 1065 platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
324} 1066}
325 1067
1068static void __init ap4evb_timer_init(void)
1069{
1070 sh7372_clock_init();
1071 shmobile_timer.init();
1072
1073 /* External clock source */
1074 clk_set_rate(&dv_clki_clk, 27000000);
1075}
1076
1077static struct sys_timer ap4evb_timer = {
1078 .init = ap4evb_timer_init,
1079};
1080
326MACHINE_START(AP4EVB, "ap4evb") 1081MACHINE_START(AP4EVB, "ap4evb")
327 .phys_io = 0xe6000000, 1082 .phys_io = 0xe6000000,
328 .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc, 1083 .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc,
329 .map_io = ap4evb_map_io, 1084 .map_io = ap4evb_map_io,
330 .init_irq = sh7372_init_irq, 1085 .init_irq = sh7372_init_irq,
331 .init_machine = ap4evb_init, 1086 .init_machine = ap4evb_init,
332 .timer = &shmobile_timer, 1087 .timer = &ap4evb_timer,
333MACHINE_END 1088MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
index 9247503296c..a5525901e91 100644
--- a/arch/arm/mach-shmobile/board-g3evm.c
+++ b/arch/arm/mach-shmobile/board-g3evm.c
@@ -37,6 +37,15 @@
37#include <asm/mach-types.h> 37#include <asm/mach-types.h>
38#include <asm/mach/arch.h> 38#include <asm/mach/arch.h>
39#include <asm/mach/map.h> 39#include <asm/mach/map.h>
40#include <asm/mach/time.h>
41
42/*
43 * IrDA
44 *
45 * S67: 5bit : ON power
46 * : 6bit : ON remote control
47 * OFF IrDA
48 */
40 49
41static struct mtd_partition nor_flash_partitions[] = { 50static struct mtd_partition nor_flash_partitions[] = {
42 { 51 {
@@ -91,7 +100,7 @@ static struct platform_device nor_flash_device = {
91}; 100};
92 101
93/* USBHS */ 102/* USBHS */
94void usb_host_port_power(int port, int power) 103static void usb_host_port_power(int port, int power)
95{ 104{
96 if (!power) /* only power-on supported for now */ 105 if (!power) /* only power-on supported for now */
97 return; 106 return;
@@ -113,7 +122,7 @@ static struct resource usb_host_resources[] = {
113 .flags = IORESOURCE_MEM, 122 .flags = IORESOURCE_MEM,
114 }, 123 },
115 [1] = { 124 [1] = {
116 .start = 65, 125 .start = evt2irq(0xa20), /* USBHS_USHI0 */
117 .flags = IORESOURCE_IRQ, 126 .flags = IORESOURCE_IRQ,
118 }, 127 },
119}; 128};
@@ -153,7 +162,7 @@ static struct resource keysc_resources[] = {
153 .flags = IORESOURCE_MEM, 162 .flags = IORESOURCE_MEM,
154 }, 163 },
155 [1] = { 164 [1] = {
156 .start = 79, 165 .start = evt2irq(0xbe0), /* KEYSC_KEY */
157 .flags = IORESOURCE_IRQ, 166 .flags = IORESOURCE_IRQ,
158 }, 167 },
159}; 168};
@@ -209,11 +218,31 @@ static struct platform_device nand_flash_device = {
209 }, 218 },
210}; 219};
211 220
221static struct resource irda_resources[] = {
222 [0] = {
223 .start = 0xE6D00000,
224 .end = 0xE6D01FD4 - 1,
225 .flags = IORESOURCE_MEM,
226 },
227 [1] = {
228 .start = evt2irq(0x480), /* IRDA */
229 .flags = IORESOURCE_IRQ,
230 },
231};
232
233static struct platform_device irda_device = {
234 .name = "sh_irda",
235 .id = -1,
236 .resource = irda_resources,
237 .num_resources = ARRAY_SIZE(irda_resources),
238};
239
212static struct platform_device *g3evm_devices[] __initdata = { 240static struct platform_device *g3evm_devices[] __initdata = {
213 &nor_flash_device, 241 &nor_flash_device,
214 &usb_host_device, 242 &usb_host_device,
215 &keysc_device, 243 &keysc_device,
216 &nand_flash_device, 244 &nand_flash_device,
245 &irda_device,
217}; 246};
218 247
219static struct map_desc g3evm_io_desc[] __initdata = { 248static struct map_desc g3evm_io_desc[] __initdata = {
@@ -232,9 +261,8 @@ static void __init g3evm_map_io(void)
232{ 261{
233 iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc)); 262 iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc));
234 263
235 /* setup early devices, clocks and console here as well */ 264 /* setup early devices and console here as well */
236 sh7367_add_early_devices(); 265 sh7367_add_early_devices();
237 sh7367_clock_init();
238 shmobile_setup_console(); 266 shmobile_setup_console();
239} 267}
240 268
@@ -271,9 +299,6 @@ static void __init g3evm_init(void)
271 gpio_request(GPIO_FN_EXTLP, NULL); 299 gpio_request(GPIO_FN_EXTLP, NULL);
272 gpio_request(GPIO_FN_IDIN, NULL); 300 gpio_request(GPIO_FN_IDIN, NULL);
273 301
274 /* enable clock in SYMSTPCR2 */
275 __raw_writel(__raw_readl(0xe6158048) & ~(1 << 22), 0xe6158048);
276
277 /* setup USB phy */ 302 /* setup USB phy */
278 __raw_writew(0x0300, 0xe605810a); /* USBCR1 */ 303 __raw_writew(0x0300, 0xe605810a); /* USBCR1 */
279 __raw_writew(0x00e0, 0xe60581c0); /* CPFCH */ 304 __raw_writew(0x00e0, 0xe60581c0); /* CPFCH */
@@ -318,16 +343,32 @@ static void __init g3evm_init(void)
318 /* FOE, FCDE, FSC on dedicated pins */ 343 /* FOE, FCDE, FSC on dedicated pins */
319 __raw_writel(__raw_readl(0xe6158048) & ~(1 << 15), 0xe6158048); 344 __raw_writel(__raw_readl(0xe6158048) & ~(1 << 15), 0xe6158048);
320 345
346 /* IrDA */
347 gpio_request(GPIO_FN_IRDA_OUT, NULL);
348 gpio_request(GPIO_FN_IRDA_IN, NULL);
349 gpio_request(GPIO_FN_IRDA_FIRSEL, NULL);
350 set_irq_type(evt2irq(0x480), IRQ_TYPE_LEVEL_LOW);
351
321 sh7367_add_standard_devices(); 352 sh7367_add_standard_devices();
322 353
323 platform_add_devices(g3evm_devices, ARRAY_SIZE(g3evm_devices)); 354 platform_add_devices(g3evm_devices, ARRAY_SIZE(g3evm_devices));
324} 355}
325 356
357static void __init g3evm_timer_init(void)
358{
359 sh7367_clock_init();
360 shmobile_timer.init();
361}
362
363static struct sys_timer g3evm_timer = {
364 .init = g3evm_timer_init,
365};
366
326MACHINE_START(G3EVM, "g3evm") 367MACHINE_START(G3EVM, "g3evm")
327 .phys_io = 0xe6000000, 368 .phys_io = 0xe6000000,
328 .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc, 369 .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc,
329 .map_io = g3evm_map_io, 370 .map_io = g3evm_map_io,
330 .init_irq = sh7367_init_irq, 371 .init_irq = sh7367_init_irq,
331 .init_machine = g3evm_init, 372 .init_machine = g3evm_init,
332 .timer = &shmobile_timer, 373 .timer = &g3evm_timer,
333MACHINE_END 374MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
index 10673a90be5..2c3ff6f7f34 100644
--- a/arch/arm/mach-shmobile/board-g4evm.c
+++ b/arch/arm/mach-shmobile/board-g4evm.c
@@ -30,12 +30,39 @@
30#include <linux/io.h> 30#include <linux/io.h>
31#include <linux/input.h> 31#include <linux/input.h>
32#include <linux/input/sh_keysc.h> 32#include <linux/input/sh_keysc.h>
33#include <linux/mfd/sh_mobile_sdhi.h>
33#include <linux/gpio.h> 34#include <linux/gpio.h>
34#include <mach/sh7377.h> 35#include <mach/sh7377.h>
35#include <mach/common.h> 36#include <mach/common.h>
36#include <asm/mach-types.h> 37#include <asm/mach-types.h>
37#include <asm/mach/arch.h> 38#include <asm/mach/arch.h>
38#include <asm/mach/map.h> 39#include <asm/mach/map.h>
40#include <asm/mach/time.h>
41
42/*
43 * SDHI
44 *
45 * SDHI0 : card detection is possible
46 * SDHI1 : card detection is impossible
47 *
48 * [G4-MAIN-BOARD]
49 * JP74 : short # DBG_2V8A for SDHI0
50 * JP75 : NC # DBG_3V3A for SDHI0
51 * JP76 : NC # DBG_3V3A_SD for SDHI0
52 * JP77 : NC # 3V3A_SDIO for SDHI1
53 * JP78 : short # DBG_2V8A for SDHI1
54 * JP79 : NC # DBG_3V3A for SDHI1
55 * JP80 : NC # DBG_3V3A_SD for SDHI1
56 *
57 * [G4-CORE-BOARD]
58 * S32 : all off # to dissever from G3-CORE_DBG board
59 * S33 : all off # to dissever from G3-CORE_DBG board
60 *
61 * [G3-CORE_DBG-BOARD]
62 * S1 : all off # to dissever from G3-CORE_DBG board
63 * S3 : all off # to dissever from G3-CORE_DBG board
64 * S4 : all off # to dissever from G3-CORE_DBG board
65 */
39 66
40static struct mtd_partition nor_flash_partitions[] = { 67static struct mtd_partition nor_flash_partitions[] = {
41 { 68 {
@@ -90,7 +117,7 @@ static struct platform_device nor_flash_device = {
90}; 117};
91 118
92/* USBHS */ 119/* USBHS */
93void usb_host_port_power(int port, int power) 120static void usb_host_port_power(int port, int power)
94{ 121{
95 if (!power) /* only power-on supported for now */ 122 if (!power) /* only power-on supported for now */
96 return; 123 return;
@@ -112,8 +139,7 @@ static struct resource usb_host_resources[] = {
112 .flags = IORESOURCE_MEM, 139 .flags = IORESOURCE_MEM,
113 }, 140 },
114 [1] = { 141 [1] = {
115 .start = 65, 142 .start = evt2irq(0x0a20), /* USBHS_USHI0 */
116 .end = 65,
117 .flags = IORESOURCE_IRQ, 143 .flags = IORESOURCE_IRQ,
118 }, 144 },
119}; 145};
@@ -154,7 +180,7 @@ static struct resource keysc_resources[] = {
154 .flags = IORESOURCE_MEM, 180 .flags = IORESOURCE_MEM,
155 }, 181 },
156 [1] = { 182 [1] = {
157 .start = 79, 183 .start = evt2irq(0x0be0), /* KEYSC_KEY */
158 .flags = IORESOURCE_IRQ, 184 .flags = IORESOURCE_IRQ,
159 }, 185 },
160}; 186};
@@ -169,10 +195,53 @@ static struct platform_device keysc_device = {
169 }, 195 },
170}; 196};
171 197
198/* SDHI */
199static struct resource sdhi0_resources[] = {
200 [0] = {
201 .name = "SDHI0",
202 .start = 0xe6d50000,
203 .end = 0xe6d501ff,
204 .flags = IORESOURCE_MEM,
205 },
206 [1] = {
207 .start = evt2irq(0x0e00), /* SDHI0 */
208 .flags = IORESOURCE_IRQ,
209 },
210};
211
212static struct platform_device sdhi0_device = {
213 .name = "sh_mobile_sdhi",
214 .num_resources = ARRAY_SIZE(sdhi0_resources),
215 .resource = sdhi0_resources,
216 .id = 0,
217};
218
219static struct resource sdhi1_resources[] = {
220 [0] = {
221 .name = "SDHI1",
222 .start = 0xe6d60000,
223 .end = 0xe6d601ff,
224 .flags = IORESOURCE_MEM,
225 },
226 [1] = {
227 .start = evt2irq(0x0e80), /* SDHI1 */
228 .flags = IORESOURCE_IRQ,
229 },
230};
231
232static struct platform_device sdhi1_device = {
233 .name = "sh_mobile_sdhi",
234 .num_resources = ARRAY_SIZE(sdhi1_resources),
235 .resource = sdhi1_resources,
236 .id = 1,
237};
238
172static struct platform_device *g4evm_devices[] __initdata = { 239static struct platform_device *g4evm_devices[] __initdata = {
173 &nor_flash_device, 240 &nor_flash_device,
174 &usb_host_device, 241 &usb_host_device,
175 &keysc_device, 242 &keysc_device,
243 &sdhi0_device,
244 &sdhi1_device,
176}; 245};
177 246
178static struct map_desc g4evm_io_desc[] __initdata = { 247static struct map_desc g4evm_io_desc[] __initdata = {
@@ -191,12 +260,41 @@ static void __init g4evm_map_io(void)
191{ 260{
192 iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc)); 261 iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc));
193 262
194 /* setup early devices, clocks and console here as well */ 263 /* setup early devices and console here as well */
195 sh7377_add_early_devices(); 264 sh7377_add_early_devices();
196 sh7367_clock_init(); /* use g3 clocks for now */
197 shmobile_setup_console(); 265 shmobile_setup_console();
198} 266}
199 267
268#define GPIO_SDHID0_D0 0xe60520fc
269#define GPIO_SDHID0_D1 0xe60520fd
270#define GPIO_SDHID0_D2 0xe60520fe
271#define GPIO_SDHID0_D3 0xe60520ff
272#define GPIO_SDHICMD0 0xe6052100
273
274#define GPIO_SDHID1_D0 0xe6052103
275#define GPIO_SDHID1_D1 0xe6052104
276#define GPIO_SDHID1_D2 0xe6052105
277#define GPIO_SDHID1_D3 0xe6052106
278#define GPIO_SDHICMD1 0xe6052107
279
280/*
281 * FIXME !!
282 *
283 * gpio_pull_up is quick_hack.
284 *
285 * current gpio frame work doesn't have
286 * the method to control only pull up/down/free.
287 * this function should be replaced by correct gpio function
288 */
289static void __init gpio_pull_up(u32 addr)
290{
291 u8 data = __raw_readb(addr);
292
293 data &= 0x0F;
294 data |= 0xC0;
295 __raw_writeb(data, addr);
296}
297
200static void __init g4evm_init(void) 298static void __init g4evm_init(void)
201{ 299{
202 sh7377_pinmux_init(); 300 sh7377_pinmux_init();
@@ -229,9 +327,6 @@ static void __init g4evm_init(void)
229 gpio_request(GPIO_FN_EXTLP, NULL); 327 gpio_request(GPIO_FN_EXTLP, NULL);
230 gpio_request(GPIO_FN_IDIN, NULL); 328 gpio_request(GPIO_FN_IDIN, NULL);
231 329
232 /* enable clock in SMSTPCR3 */
233 __raw_writel(__raw_readl(0xe615013c) & ~(1 << 22), 0xe615013c);
234
235 /* setup USB phy */ 330 /* setup USB phy */
236 __raw_writew(0x0200, 0xe605810a); /* USBCR1 */ 331 __raw_writew(0x0200, 0xe605810a); /* USBCR1 */
237 __raw_writew(0x00e0, 0xe60581c0); /* CPFCH */ 332 __raw_writew(0x00e0, 0xe60581c0); /* CPFCH */
@@ -253,16 +348,54 @@ static void __init g4evm_init(void)
253 gpio_request(GPIO_FN_PORT71_KEYIN5_PU, NULL); 348 gpio_request(GPIO_FN_PORT71_KEYIN5_PU, NULL);
254 gpio_request(GPIO_FN_PORT72_KEYIN6_PU, NULL); 349 gpio_request(GPIO_FN_PORT72_KEYIN6_PU, NULL);
255 350
351 /* SDHI0 */
352 gpio_request(GPIO_FN_SDHICLK0, NULL);
353 gpio_request(GPIO_FN_SDHICD0, NULL);
354 gpio_request(GPIO_FN_SDHID0_0, NULL);
355 gpio_request(GPIO_FN_SDHID0_1, NULL);
356 gpio_request(GPIO_FN_SDHID0_2, NULL);
357 gpio_request(GPIO_FN_SDHID0_3, NULL);
358 gpio_request(GPIO_FN_SDHICMD0, NULL);
359 gpio_request(GPIO_FN_SDHIWP0, NULL);
360 gpio_pull_up(GPIO_SDHID0_D0);
361 gpio_pull_up(GPIO_SDHID0_D1);
362 gpio_pull_up(GPIO_SDHID0_D2);
363 gpio_pull_up(GPIO_SDHID0_D3);
364 gpio_pull_up(GPIO_SDHICMD0);
365
366 /* SDHI1 */
367 gpio_request(GPIO_FN_SDHICLK1, NULL);
368 gpio_request(GPIO_FN_SDHID1_0, NULL);
369 gpio_request(GPIO_FN_SDHID1_1, NULL);
370 gpio_request(GPIO_FN_SDHID1_2, NULL);
371 gpio_request(GPIO_FN_SDHID1_3, NULL);
372 gpio_request(GPIO_FN_SDHICMD1, NULL);
373 gpio_pull_up(GPIO_SDHID1_D0);
374 gpio_pull_up(GPIO_SDHID1_D1);
375 gpio_pull_up(GPIO_SDHID1_D2);
376 gpio_pull_up(GPIO_SDHID1_D3);
377 gpio_pull_up(GPIO_SDHICMD1);
378
256 sh7377_add_standard_devices(); 379 sh7377_add_standard_devices();
257 380
258 platform_add_devices(g4evm_devices, ARRAY_SIZE(g4evm_devices)); 381 platform_add_devices(g4evm_devices, ARRAY_SIZE(g4evm_devices));
259} 382}
260 383
384static void __init g4evm_timer_init(void)
385{
386 sh7377_clock_init();
387 shmobile_timer.init();
388}
389
390static struct sys_timer g4evm_timer = {
391 .init = g4evm_timer_init,
392};
393
261MACHINE_START(G4EVM, "g4evm") 394MACHINE_START(G4EVM, "g4evm")
262 .phys_io = 0xe6000000, 395 .phys_io = 0xe6000000,
263 .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc, 396 .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc,
264 .map_io = g4evm_map_io, 397 .map_io = g4evm_map_io,
265 .init_irq = sh7377_init_irq, 398 .init_irq = sh7377_init_irq,
266 .init_machine = g4evm_init, 399 .init_machine = g4evm_init,
267 .timer = &shmobile_timer, 400 .timer = &g4evm_timer,
268MACHINE_END 401MACHINE_END
diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c
index bb940c6e4e6..b6454c9f2ab 100644
--- a/arch/arm/mach-shmobile/clock-sh7367.c
+++ b/arch/arm/mach-shmobile/clock-sh7367.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Preliminary clock framework support for sh7367 2 * SH7367 clock framework support
3 * 3 *
4 * Copyright (C) 2010 Magnus Damm 4 * Copyright (C) 2010 Magnus Damm
5 * 5 *
@@ -17,87 +17,342 @@
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */ 18 */
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/kernel.h> 20#include <linux/kernel.h>
22#include <linux/list.h> 21#include <linux/io.h>
23#include <linux/clk.h> 22#include <linux/sh_clk.h>
23#include <mach/common.h>
24#include <asm/clkdev.h>
25
26/* SH7367 registers */
27#define RTFRQCR 0xe6150000
28#define SYFRQCR 0xe6150004
29#define CMFRQCR 0xe61500E0
30#define VCLKCR1 0xe6150008
31#define VCLKCR2 0xe615000C
32#define VCLKCR3 0xe615001C
33#define SCLKACR 0xe6150010
34#define SCLKBCR 0xe6150014
35#define SUBUSBCKCR 0xe6158080
36#define SPUCKCR 0xe6150084
37#define MSUCKCR 0xe6150088
38#define MVI3CKCR 0xe6150090
39#define VOUCKCR 0xe6150094
40#define MFCK1CR 0xe6150098
41#define MFCK2CR 0xe615009C
42#define PLLC1CR 0xe6150028
43#define PLLC2CR 0xe615002C
44#define RTMSTPCR0 0xe6158030
45#define RTMSTPCR2 0xe6158038
46#define SYMSTPCR0 0xe6158040
47#define SYMSTPCR2 0xe6158048
48#define CMMSTPCR0 0xe615804c
24 49
25struct clk { 50/* Fixed 32 KHz root clock from EXTALR pin */
26 const char *name; 51static struct clk r_clk = {
27 unsigned long rate; 52 .rate = 32768,
28}; 53};
29 54
30#include <asm/clkdev.h> 55/*
56 * 26MHz default rate for the EXTALB1 root input clock.
57 * If needed, reset this with clk_set_rate() from the platform code.
58 */
59struct clk sh7367_extalb1_clk = {
60 .rate = 26666666,
61};
31 62
32int __clk_get(struct clk *clk) 63/*
33{ 64 * 48MHz default rate for the EXTAL2 root input clock.
34 return 1; 65 * If needed, reset this with clk_set_rate() from the platform code.
35} 66 */
36EXPORT_SYMBOL(__clk_get); 67struct clk sh7367_extal2_clk = {
68 .rate = 48000000,
69};
37 70
38void __clk_put(struct clk *clk) 71/* A fixed divide-by-2 block */
72static unsigned long div2_recalc(struct clk *clk)
39{ 73{
74 return clk->parent->rate / 2;
40} 75}
41EXPORT_SYMBOL(__clk_put);
42 76
77static struct clk_ops div2_clk_ops = {
78 .recalc = div2_recalc,
79};
80
81/* Divide extalb1 by two */
82static struct clk extalb1_div2_clk = {
83 .ops = &div2_clk_ops,
84 .parent = &sh7367_extalb1_clk,
85};
86
87/* Divide extal2 by two */
88static struct clk extal2_div2_clk = {
89 .ops = &div2_clk_ops,
90 .parent = &sh7367_extal2_clk,
91};
43 92
44int clk_enable(struct clk *clk) 93/* PLLC1 */
94static unsigned long pllc1_recalc(struct clk *clk)
45{ 95{
46 return 0; 96 unsigned long mult = 1;
97
98 if (__raw_readl(PLLC1CR) & (1 << 14))
99 mult = (((__raw_readl(RTFRQCR) >> 24) & 0x3f) + 1) * 2;
100
101 return clk->parent->rate * mult;
47} 102}
48EXPORT_SYMBOL(clk_enable);
49 103
50void clk_disable(struct clk *clk) 104static struct clk_ops pllc1_clk_ops = {
105 .recalc = pllc1_recalc,
106};
107
108static struct clk pllc1_clk = {
109 .ops = &pllc1_clk_ops,
110 .flags = CLK_ENABLE_ON_INIT,
111 .parent = &extalb1_div2_clk,
112};
113
114/* Divide PLLC1 by two */
115static struct clk pllc1_div2_clk = {
116 .ops = &div2_clk_ops,
117 .parent = &pllc1_clk,
118};
119
120/* PLLC2 */
121static unsigned long pllc2_recalc(struct clk *clk)
51{ 122{
123 unsigned long mult = 1;
124
125 if (__raw_readl(PLLC2CR) & (1 << 31))
126 mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2;
127
128 return clk->parent->rate * mult;
52} 129}
53EXPORT_SYMBOL(clk_disable);
54 130
55unsigned long clk_get_rate(struct clk *clk) 131static struct clk_ops pllc2_clk_ops = {
132 .recalc = pllc2_recalc,
133};
134
135static struct clk pllc2_clk = {
136 .ops = &pllc2_clk_ops,
137 .flags = CLK_ENABLE_ON_INIT,
138 .parent = &extalb1_div2_clk,
139};
140
141static struct clk *main_clks[] = {
142 &r_clk,
143 &sh7367_extalb1_clk,
144 &sh7367_extal2_clk,
145 &extalb1_div2_clk,
146 &extal2_div2_clk,
147 &pllc1_clk,
148 &pllc1_div2_clk,
149 &pllc2_clk,
150};
151
152static void div4_kick(struct clk *clk)
56{ 153{
57 return clk ? clk->rate : 0; 154 unsigned long value;
155
156 /* set KICK bit in SYFRQCR to update hardware setting */
157 value = __raw_readl(SYFRQCR);
158 value |= (1 << 31);
159 __raw_writel(value, SYFRQCR);
58} 160}
59EXPORT_SYMBOL(clk_get_rate);
60 161
61/* a static peripheral clock for now - enough to get sh-sci working */ 162static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
62static struct clk peripheral_clk = { 163 24, 32, 36, 48, 0, 72, 0, 0 };
63 .name = "peripheral_clk", 164
64 .rate = 48000000, 165static struct clk_div_mult_table div4_div_mult_table = {
166 .divisors = divisors,
167 .nr_divisors = ARRAY_SIZE(divisors),
65}; 168};
66 169
67/* a static rclk for now - enough to get sh_cmt working */ 170static struct clk_div4_table div4_table = {
68static struct clk r_clk = { 171 .div_mult_table = &div4_div_mult_table,
69 .name = "r_clk", 172 .kick = div4_kick,
70 .rate = 32768, 173};
174
175enum { DIV4_I, DIV4_G, DIV4_S, DIV4_B,
176 DIV4_ZX, DIV4_ZT, DIV4_Z, DIV4_ZD, DIV4_HP,
177 DIV4_ZS, DIV4_ZB, DIV4_ZB3, DIV4_CP, DIV4_NR };
178
179#define DIV4(_reg, _bit, _mask, _flags) \
180 SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
181
182static struct clk div4_clks[DIV4_NR] = {
183 [DIV4_I] = DIV4(RTFRQCR, 20, 0x6fff, CLK_ENABLE_ON_INIT),
184 [DIV4_G] = DIV4(RTFRQCR, 16, 0x6fff, CLK_ENABLE_ON_INIT),
185 [DIV4_S] = DIV4(RTFRQCR, 12, 0x6fff, CLK_ENABLE_ON_INIT),
186 [DIV4_B] = DIV4(RTFRQCR, 8, 0x6fff, CLK_ENABLE_ON_INIT),
187 [DIV4_ZX] = DIV4(SYFRQCR, 20, 0x6fff, 0),
188 [DIV4_ZT] = DIV4(SYFRQCR, 16, 0x6fff, 0),
189 [DIV4_Z] = DIV4(SYFRQCR, 12, 0x6fff, 0),
190 [DIV4_ZD] = DIV4(SYFRQCR, 8, 0x6fff, 0),
191 [DIV4_HP] = DIV4(SYFRQCR, 4, 0x6fff, 0),
192 [DIV4_ZS] = DIV4(CMFRQCR, 12, 0x6fff, 0),
193 [DIV4_ZB] = DIV4(CMFRQCR, 8, 0x6fff, 0),
194 [DIV4_ZB3] = DIV4(CMFRQCR, 4, 0x6fff, 0),
195 [DIV4_CP] = DIV4(CMFRQCR, 0, 0x6fff, 0),
71}; 196};
72 197
73/* a static usb0 for now - enough to get r8a66597 working */ 198enum { DIV6_SUB, DIV6_SIUA, DIV6_SIUB, DIV6_MSU, DIV6_SPU,
74static struct clk usb0_clk = { 199 DIV6_MVI3, DIV6_MF1, DIV6_MF2,
75 .name = "usb0", 200 DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_VOU,
201 DIV6_NR };
202
203static struct clk div6_clks[DIV6_NR] = {
204 [DIV6_SUB] = SH_CLK_DIV6(&sh7367_extal2_clk, SUBUSBCKCR, 0),
205 [DIV6_SIUA] = SH_CLK_DIV6(&pllc1_div2_clk, SCLKACR, 0),
206 [DIV6_SIUB] = SH_CLK_DIV6(&pllc1_div2_clk, SCLKBCR, 0),
207 [DIV6_MSU] = SH_CLK_DIV6(&pllc1_div2_clk, MSUCKCR, 0),
208 [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0),
209 [DIV6_MVI3] = SH_CLK_DIV6(&pllc1_div2_clk, MVI3CKCR, 0),
210 [DIV6_MF1] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK1CR, 0),
211 [DIV6_MF2] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK2CR, 0),
212 [DIV6_VCK1] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR1, 0),
213 [DIV6_VCK2] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR2, 0),
214 [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0),
215 [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0),
76}; 216};
77 217
78/* a static keysc0 clk for now - enough to get sh_keysc working */ 218enum { RTMSTP001,
79static struct clk keysc0_clk = { 219 RTMSTP231, RTMSTP230, RTMSTP229, RTMSTP228, RTMSTP226,
80 .name = "keysc0", 220 RTMSTP216, RTMSTP206, RTMSTP205, RTMSTP201,
221 SYMSTP023, SYMSTP007, SYMSTP006, SYMSTP004,
222 SYMSTP003, SYMSTP002, SYMSTP001, SYMSTP000,
223 SYMSTP231, SYMSTP229, SYMSTP225, SYMSTP223, SYMSTP222,
224 SYMSTP215, SYMSTP214, SYMSTP213, SYMSTP211,
225 CMMSTP003,
226 MSTP_NR };
227
228#define MSTP(_parent, _reg, _bit, _flags) \
229 SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
230
231static struct clk mstp_clks[MSTP_NR] = {
232 [RTMSTP001] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR0, 1, 0), /* IIC2 */
233 [RTMSTP231] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 31, 0), /* VEU3 */
234 [RTMSTP230] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 30, 0), /* VEU2 */
235 [RTMSTP229] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 29, 0), /* VEU1 */
236 [RTMSTP228] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 28, 0), /* VEU0 */
237 [RTMSTP226] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 26, 0), /* VEU2H */
238 [RTMSTP216] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR2, 16, 0), /* IIC0 */
239 [RTMSTP206] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 6, 0), /* JPU */
240 [RTMSTP205] = MSTP(&div6_clks[DIV6_VOU], RTMSTPCR2, 5, 0), /* VOU */
241 [RTMSTP201] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 1, 0), /* VPU */
242 [SYMSTP023] = MSTP(&div6_clks[DIV6_SPU], SYMSTPCR0, 23, 0), /* SPU1 */
243 [SYMSTP007] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 7, 0), /* SCIFA5 */
244 [SYMSTP006] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 6, 0), /* SCIFB */
245 [SYMSTP004] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 4, 0), /* SCIFA0 */
246 [SYMSTP003] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 3, 0), /* SCIFA1 */
247 [SYMSTP002] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 2, 0), /* SCIFA2 */
248 [SYMSTP001] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 1, 0), /* SCIFA3 */
249 [SYMSTP000] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 0, 0), /* SCIFA4 */
250 [SYMSTP231] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 31, 0), /* SIU */
251 [SYMSTP229] = MSTP(&r_clk, SYMSTPCR2, 29, 0), /* CMT10 */
252 [SYMSTP225] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 25, 0), /* IRDA */
253 [SYMSTP223] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 23, 0), /* IIC1 */
254 [SYMSTP222] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 22, 0), /* USBHS */
255 [SYMSTP215] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 15, 0), /* FLCTL */
256 [SYMSTP214] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 14, 0), /* SDHI0 */
257 [SYMSTP213] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 13, 0), /* SDHI1 */
258 [SYMSTP211] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 11, 0), /* SDHI2 */
259 [CMMSTP003] = MSTP(&r_clk, CMMSTPCR0, 3, 0), /* KEYSC */
81}; 260};
82 261
262#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
263#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
264
83static struct clk_lookup lookups[] = { 265static struct clk_lookup lookups[] = {
84 { 266 /* main clocks */
85 .clk = &peripheral_clk, 267 CLKDEV_CON_ID("r_clk", &r_clk),
86 }, { 268 CLKDEV_CON_ID("extalb1", &sh7367_extalb1_clk),
87 .clk = &r_clk, 269 CLKDEV_CON_ID("extal2", &sh7367_extal2_clk),
88 }, { 270 CLKDEV_CON_ID("extalb1_div2_clk", &extalb1_div2_clk),
89 .clk = &usb0_clk, 271 CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk),
90 }, { 272 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
91 .clk = &keysc0_clk, 273 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
92 } 274 CLKDEV_CON_ID("pllc2_clk", &pllc2_clk),
275
276 /* DIV4 clocks */
277 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
278 CLKDEV_CON_ID("g_clk", &div4_clks[DIV4_G]),
279 CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
280 CLKDEV_CON_ID("zx_clk", &div4_clks[DIV4_ZX]),
281 CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]),
282 CLKDEV_CON_ID("z_clk", &div4_clks[DIV4_Z]),
283 CLKDEV_CON_ID("zd_clk", &div4_clks[DIV4_ZD]),
284 CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
285 CLKDEV_CON_ID("zs_clk", &div4_clks[DIV4_ZS]),
286 CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
287 CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]),
288 CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
289
290 /* DIV6 clocks */
291 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
292 CLKDEV_CON_ID("siua_clk", &div6_clks[DIV6_SIUA]),
293 CLKDEV_CON_ID("siub_clk", &div6_clks[DIV6_SIUB]),
294 CLKDEV_CON_ID("msu_clk", &div6_clks[DIV6_MSU]),
295 CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
296 CLKDEV_CON_ID("mvi3_clk", &div6_clks[DIV6_MVI3]),
297 CLKDEV_CON_ID("mf1_clk", &div6_clks[DIV6_MF1]),
298 CLKDEV_CON_ID("mf2_clk", &div6_clks[DIV6_MF2]),
299 CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
300 CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
301 CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
302 CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
303
304 /* MSTP32 clocks */
305 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[RTMSTP001]), /* IIC2 */
306 CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[RTMSTP231]), /* VEU3 */
307 CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[RTMSTP230]), /* VEU2 */
308 CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[RTMSTP229]), /* VEU1 */
309 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[RTMSTP228]), /* VEU0 */
310 CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[RTMSTP226]), /* VEU2H */
311 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[RTMSTP216]), /* IIC0 */
312 CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[RTMSTP206]), /* JPU */
313 CLKDEV_DEV_ID("sh-vou", &mstp_clks[RTMSTP205]), /* VOU */
314 CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[RTMSTP201]), /* VPU */
315 CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[SYMSTP023]), /* SPU1 */
316 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[SYMSTP007]), /* SCIFA5 */
317 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[SYMSTP006]), /* SCIFB */
318 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[SYMSTP004]), /* SCIFA0 */
319 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[SYMSTP003]), /* SCIFA1 */
320 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[SYMSTP002]), /* SCIFA2 */
321 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */
322 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */
323 CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */
324 CLKDEV_CON_ID("cmt1", &mstp_clks[SYMSTP229]), /* CMT10 */
325 CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */
326 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */
327 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */
328 CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[SYMSTP222]), /* USBHS */
329 CLKDEV_DEV_ID("sh_flctl", &mstp_clks[SYMSTP215]), /* FLCTL */
330 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[SYMSTP214]), /* SDHI0 */
331 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[SYMSTP213]), /* SDHI1 */
332 CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[SYMSTP211]), /* SDHI2 */
333 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[CMMSTP003]), /* KEYSC */
93}; 334};
94 335
95void __init sh7367_clock_init(void) 336void __init sh7367_clock_init(void)
96{ 337{
97 int i; 338 int k, ret = 0;
339
340 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
341 ret = clk_register(main_clks[k]);
342
343 if (!ret)
344 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
345
346 if (!ret)
347 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
348
349 if (!ret)
350 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
351
352 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
98 353
99 for (i = 0; i < ARRAY_SIZE(lookups); i++) { 354 if (!ret)
100 lookups[i].con_id = lookups[i].clk->name; 355 clk_init();
101 clkdev_add(&lookups[i]); 356 else
102 } 357 panic("failed to setup sh7367 clocks\n");
103} 358}
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
new file mode 100644
index 00000000000..fb4e9b1d788
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -0,0 +1,560 @@
1/*
2 * SH7372 clock framework support
3 *
4 * Copyright (C) 2010 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 as published by
8 * the Free Software Foundation; either version 2 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <linux/init.h>
20#include <linux/kernel.h>
21#include <linux/io.h>
22#include <linux/sh_clk.h>
23#include <mach/common.h>
24#include <asm/clkdev.h>
25
26/* SH7372 registers */
27#define FRQCRA 0xe6150000
28#define FRQCRB 0xe6150004
29#define FRQCRC 0xe61500e0
30#define FRQCRD 0xe61500e4
31#define VCLKCR1 0xe6150008
32#define VCLKCR2 0xe615000c
33#define VCLKCR3 0xe615001c
34#define FMSICKCR 0xe6150010
35#define FMSOCKCR 0xe6150014
36#define FSIACKCR 0xe6150018
37#define FSIBCKCR 0xe6150090
38#define SUBCKCR 0xe6150080
39#define SPUCKCR 0xe6150084
40#define VOUCKCR 0xe6150088
41#define HDMICKCR 0xe6150094
42#define DSITCKCR 0xe6150060
43#define DSI0PCKCR 0xe6150064
44#define DSI1PCKCR 0xe6150098
45#define PLLC01CR 0xe6150028
46#define PLLC2CR 0xe615002c
47#define SMSTPCR0 0xe6150130
48#define SMSTPCR1 0xe6150134
49#define SMSTPCR2 0xe6150138
50#define SMSTPCR3 0xe615013c
51#define SMSTPCR4 0xe6150140
52
53/* Platforms must set frequency on their DV_CLKI pin */
54struct clk dv_clki_clk = {
55};
56
57/* Fixed 32 KHz root clock from EXTALR pin */
58static struct clk r_clk = {
59 .rate = 32768,
60};
61
62/*
63 * 26MHz default rate for the EXTAL1 root input clock.
64 * If needed, reset this with clk_set_rate() from the platform code.
65 */
66struct clk sh7372_extal1_clk = {
67 .rate = 26000000,
68};
69
70/*
71 * 48MHz default rate for the EXTAL2 root input clock.
72 * If needed, reset this with clk_set_rate() from the platform code.
73 */
74struct clk sh7372_extal2_clk = {
75 .rate = 48000000,
76};
77
78/* A fixed divide-by-2 block */
79static unsigned long div2_recalc(struct clk *clk)
80{
81 return clk->parent->rate / 2;
82}
83
84static struct clk_ops div2_clk_ops = {
85 .recalc = div2_recalc,
86};
87
88/* Divide dv_clki by two */
89struct clk dv_clki_div2_clk = {
90 .ops = &div2_clk_ops,
91 .parent = &dv_clki_clk,
92};
93
94/* Divide extal1 by two */
95static struct clk extal1_div2_clk = {
96 .ops = &div2_clk_ops,
97 .parent = &sh7372_extal1_clk,
98};
99
100/* Divide extal2 by two */
101static struct clk extal2_div2_clk = {
102 .ops = &div2_clk_ops,
103 .parent = &sh7372_extal2_clk,
104};
105
106/* Divide extal2 by four */
107static struct clk extal2_div4_clk = {
108 .ops = &div2_clk_ops,
109 .parent = &extal2_div2_clk,
110};
111
112/* PLLC0 and PLLC1 */
113static unsigned long pllc01_recalc(struct clk *clk)
114{
115 unsigned long mult = 1;
116
117 if (__raw_readl(PLLC01CR) & (1 << 14))
118 mult = (((__raw_readl(clk->enable_reg) >> 24) & 0x3f) + 1) * 2;
119
120 return clk->parent->rate * mult;
121}
122
123static struct clk_ops pllc01_clk_ops = {
124 .recalc = pllc01_recalc,
125};
126
127static struct clk pllc0_clk = {
128 .ops = &pllc01_clk_ops,
129 .flags = CLK_ENABLE_ON_INIT,
130 .parent = &extal1_div2_clk,
131 .enable_reg = (void __iomem *)FRQCRC,
132};
133
134static struct clk pllc1_clk = {
135 .ops = &pllc01_clk_ops,
136 .flags = CLK_ENABLE_ON_INIT,
137 .parent = &extal1_div2_clk,
138 .enable_reg = (void __iomem *)FRQCRA,
139};
140
141/* Divide PLLC1 by two */
142static struct clk pllc1_div2_clk = {
143 .ops = &div2_clk_ops,
144 .parent = &pllc1_clk,
145};
146
147/* PLLC2 */
148
149/* Indices are important - they are the actual src selecting values */
150static struct clk *pllc2_parent[] = {
151 [0] = &extal1_div2_clk,
152 [1] = &extal2_div2_clk,
153 [2] = &dv_clki_div2_clk,
154};
155
156/* Only multipliers 20 * 2 to 46 * 2 are valid, last entry for CPUFREQ_TABLE_END */
157static struct cpufreq_frequency_table pllc2_freq_table[29];
158
159static void pllc2_table_rebuild(struct clk *clk)
160{
161 int i;
162
163 /* Initialise PLLC2 frequency table */
164 for (i = 0; i < ARRAY_SIZE(pllc2_freq_table) - 2; i++) {
165 pllc2_freq_table[i].frequency = clk->parent->rate * (i + 20) * 2;
166 pllc2_freq_table[i].index = i;
167 }
168
169 /* This is a special entry - switching PLL off makes it a repeater */
170 pllc2_freq_table[i].frequency = clk->parent->rate;
171 pllc2_freq_table[i].index = i;
172
173 pllc2_freq_table[++i].frequency = CPUFREQ_TABLE_END;
174 pllc2_freq_table[i].index = i;
175}
176
177static unsigned long pllc2_recalc(struct clk *clk)
178{
179 unsigned long mult = 1;
180
181 pllc2_table_rebuild(clk);
182
183 /*
184 * If the PLL is off, mult == 1, clk->rate will be updated in
185 * pllc2_enable().
186 */
187 if (__raw_readl(PLLC2CR) & (1 << 31))
188 mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2;
189
190 return clk->parent->rate * mult;
191}
192
193static long pllc2_round_rate(struct clk *clk, unsigned long rate)
194{
195 return clk_rate_table_round(clk, clk->freq_table, rate);
196}
197
198static int pllc2_enable(struct clk *clk)
199{
200 int i;
201
202 __raw_writel(__raw_readl(PLLC2CR) | 0x80000000, PLLC2CR);
203
204 for (i = 0; i < 100; i++)
205 if (__raw_readl(PLLC2CR) & 0x80000000) {
206 clk->rate = pllc2_recalc(clk);
207 return 0;
208 }
209
210 pr_err("%s(): timeout!\n", __func__);
211
212 return -ETIMEDOUT;
213}
214
215static void pllc2_disable(struct clk *clk)
216{
217 __raw_writel(__raw_readl(PLLC2CR) & ~0x80000000, PLLC2CR);
218}
219
220static int pllc2_set_rate(struct clk *clk,
221 unsigned long rate, int algo_id)
222{
223 unsigned long value;
224 int idx;
225
226 idx = clk_rate_table_find(clk, clk->freq_table, rate);
227 if (idx < 0)
228 return idx;
229
230 if (rate == clk->parent->rate) {
231 pllc2_disable(clk);
232 return 0;
233 }
234
235 value = __raw_readl(PLLC2CR) & ~(0x3f << 24);
236
237 if (value & 0x80000000)
238 pllc2_disable(clk);
239
240 __raw_writel((value & ~0x80000000) | ((idx + 19) << 24), PLLC2CR);
241
242 if (value & 0x80000000)
243 return pllc2_enable(clk);
244
245 return 0;
246}
247
248static int pllc2_set_parent(struct clk *clk, struct clk *parent)
249{
250 u32 value;
251 int ret, i;
252
253 if (!clk->parent_table || !clk->parent_num)
254 return -EINVAL;
255
256 /* Search the parent */
257 for (i = 0; i < clk->parent_num; i++)
258 if (clk->parent_table[i] == parent)
259 break;
260
261 if (i == clk->parent_num)
262 return -ENODEV;
263
264 ret = clk_reparent(clk, parent);
265 if (ret < 0)
266 return ret;
267
268 value = __raw_readl(PLLC2CR) & ~(3 << 6);
269
270 __raw_writel(value | (i << 6), PLLC2CR);
271
272 /* Rebiuld the frequency table */
273 pllc2_table_rebuild(clk);
274
275 return 0;
276}
277
278static struct clk_ops pllc2_clk_ops = {
279 .recalc = pllc2_recalc,
280 .round_rate = pllc2_round_rate,
281 .set_rate = pllc2_set_rate,
282 .enable = pllc2_enable,
283 .disable = pllc2_disable,
284 .set_parent = pllc2_set_parent,
285};
286
287struct clk pllc2_clk = {
288 .ops = &pllc2_clk_ops,
289 .flags = CLK_ENABLE_ON_INIT,
290 .parent = &extal1_div2_clk,
291 .freq_table = pllc2_freq_table,
292 .parent_table = pllc2_parent,
293 .parent_num = ARRAY_SIZE(pllc2_parent),
294};
295
296static struct clk *main_clks[] = {
297 &dv_clki_clk,
298 &r_clk,
299 &sh7372_extal1_clk,
300 &sh7372_extal2_clk,
301 &dv_clki_div2_clk,
302 &extal1_div2_clk,
303 &extal2_div2_clk,
304 &extal2_div4_clk,
305 &pllc0_clk,
306 &pllc1_clk,
307 &pllc1_div2_clk,
308 &pllc2_clk,
309};
310
311static void div4_kick(struct clk *clk)
312{
313 unsigned long value;
314
315 /* set KICK bit in FRQCRB to update hardware setting */
316 value = __raw_readl(FRQCRB);
317 value |= (1 << 31);
318 __raw_writel(value, FRQCRB);
319}
320
321static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
322 24, 32, 36, 48, 0, 72, 96, 0 };
323
324static struct clk_div_mult_table div4_div_mult_table = {
325 .divisors = divisors,
326 .nr_divisors = ARRAY_SIZE(divisors),
327};
328
329static struct clk_div4_table div4_table = {
330 .div_mult_table = &div4_div_mult_table,
331 .kick = div4_kick,
332};
333
334enum { DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_CSIR,
335 DIV4_ZTR, DIV4_ZT, DIV4_ZX, DIV4_HP,
336 DIV4_ISPB, DIV4_S, DIV4_ZB, DIV4_ZB3, DIV4_CP,
337 DIV4_DDRP, DIV4_NR };
338
339#define DIV4(_reg, _bit, _mask, _flags) \
340 SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
341
342static struct clk div4_clks[DIV4_NR] = {
343 [DIV4_I] = DIV4(FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT),
344 [DIV4_ZG] = DIV4(FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT),
345 [DIV4_B] = DIV4(FRQCRA, 8, 0x6fff, CLK_ENABLE_ON_INIT),
346 [DIV4_M1] = DIV4(FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT),
347 [DIV4_CSIR] = DIV4(FRQCRA, 0, 0x6fff, 0),
348 [DIV4_ZTR] = DIV4(FRQCRB, 20, 0x6fff, 0),
349 [DIV4_ZT] = DIV4(FRQCRB, 16, 0x6fff, 0),
350 [DIV4_ZX] = DIV4(FRQCRB, 12, 0x6fff, 0),
351 [DIV4_HP] = DIV4(FRQCRB, 4, 0x6fff, 0),
352 [DIV4_ISPB] = DIV4(FRQCRC, 20, 0x6fff, 0),
353 [DIV4_S] = DIV4(FRQCRC, 12, 0x6fff, 0),
354 [DIV4_ZB] = DIV4(FRQCRC, 8, 0x6fff, 0),
355 [DIV4_ZB3] = DIV4(FRQCRC, 4, 0x6fff, 0),
356 [DIV4_CP] = DIV4(FRQCRC, 0, 0x6fff, 0),
357 [DIV4_DDRP] = DIV4(FRQCRD, 0, 0x677c, 0),
358};
359
360enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO,
361 DIV6_FSIA, DIV6_FSIB, DIV6_SUB, DIV6_SPU,
362 DIV6_VOU, DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P,
363 DIV6_NR };
364
365static struct clk div6_clks[DIV6_NR] = {
366 [DIV6_VCK1] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR1, 0),
367 [DIV6_VCK2] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR2, 0),
368 [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0),
369 [DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0),
370 [DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0),
371 [DIV6_FSIA] = SH_CLK_DIV6(&pllc1_div2_clk, FSIACKCR, 0),
372 [DIV6_FSIB] = SH_CLK_DIV6(&pllc1_div2_clk, FSIBCKCR, 0),
373 [DIV6_SUB] = SH_CLK_DIV6(&sh7372_extal2_clk, SUBCKCR, 0),
374 [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0),
375 [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0),
376 [DIV6_DSIT] = SH_CLK_DIV6(&pllc1_div2_clk, DSITCKCR, 0),
377 [DIV6_DSI0P] = SH_CLK_DIV6(&pllc1_div2_clk, DSI0PCKCR, 0),
378 [DIV6_DSI1P] = SH_CLK_DIV6(&pllc1_div2_clk, DSI1PCKCR, 0),
379};
380
381enum { DIV6_HDMI, DIV6_REPARENT_NR };
382
383/* Indices are important - they are the actual src selecting values */
384static struct clk *hdmi_parent[] = {
385 [0] = &pllc1_div2_clk,
386 [1] = &pllc2_clk,
387 [2] = &dv_clki_clk,
388 [3] = NULL, /* pllc2_div4 not implemented yet */
389};
390
391static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
392 [DIV6_HDMI] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, HDMICKCR, 0,
393 hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
394};
395
396enum { MSTP001,
397 MSTP131, MSTP130,
398 MSTP129, MSTP128,
399 MSTP118, MSTP117, MSTP116,
400 MSTP106, MSTP101, MSTP100,
401 MSTP223,
402 MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
403 MSTP329, MSTP328, MSTP323, MSTP322, MSTP314, MSTP313, MSTP312,
404 MSTP415, MSTP413, MSTP411, MSTP410, MSTP406, MSTP403,
405 MSTP_NR };
406
407#define MSTP(_parent, _reg, _bit, _flags) \
408 SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
409
410static struct clk mstp_clks[MSTP_NR] = {
411 [MSTP001] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR0, 1, 0), /* IIC2 */
412 [MSTP131] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 31, 0), /* VEU3 */
413 [MSTP130] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 30, 0), /* VEU2 */
414 [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* VEU1 */
415 [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */
416 [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */
417 [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */
418 [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
419 [MSTP106] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 6, 0), /* JPU */
420 [MSTP101] = MSTP(&div4_clks[DIV4_M1], SMSTPCR1, 1, 0), /* VPU */
421 [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
422 [MSTP223] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR2, 23, 0), /* SPU2 */
423 [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
424 [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
425 [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
426 [MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
427 [MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
428 [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
429 [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
430 [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
431 [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, CLK_ENABLE_ON_INIT), /* FSIA */
432 [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
433 [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */
434 [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
435 [MSTP313] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
436 [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
437 [MSTP415] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
438 [MSTP413] = MSTP(&pllc1_div2_clk, SMSTPCR4, 13, 0), /* HDMI */
439 [MSTP411] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 11, 0), /* IIC3 */
440 [MSTP410] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 10, 0), /* IIC4 */
441 [MSTP406] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 6, 0), /* USB1 */
442 [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
443};
444
445#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
446#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
447
448static struct clk_lookup lookups[] = {
449 /* main clocks */
450 CLKDEV_CON_ID("dv_clki_div2_clk", &dv_clki_div2_clk),
451 CLKDEV_CON_ID("r_clk", &r_clk),
452 CLKDEV_CON_ID("extal1", &sh7372_extal1_clk),
453 CLKDEV_CON_ID("extal2", &sh7372_extal2_clk),
454 CLKDEV_CON_ID("extal1_div2_clk", &extal1_div2_clk),
455 CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk),
456 CLKDEV_CON_ID("extal2_div4_clk", &extal2_div4_clk),
457 CLKDEV_CON_ID("pllc0_clk", &pllc0_clk),
458 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
459 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
460 CLKDEV_CON_ID("pllc2_clk", &pllc2_clk),
461
462 /* DIV4 clocks */
463 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
464 CLKDEV_CON_ID("zg_clk", &div4_clks[DIV4_ZG]),
465 CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
466 CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]),
467 CLKDEV_CON_ID("csir_clk", &div4_clks[DIV4_CSIR]),
468 CLKDEV_CON_ID("ztr_clk", &div4_clks[DIV4_ZTR]),
469 CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]),
470 CLKDEV_CON_ID("zx_clk", &div4_clks[DIV4_ZX]),
471 CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
472 CLKDEV_CON_ID("ispb_clk", &div4_clks[DIV4_ISPB]),
473 CLKDEV_CON_ID("s_clk", &div4_clks[DIV4_S]),
474 CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
475 CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]),
476 CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
477 CLKDEV_CON_ID("ddrp_clk", &div4_clks[DIV4_DDRP]),
478
479 /* DIV6 clocks */
480 CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
481 CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
482 CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
483 CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]),
484 CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]),
485 CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FSIA]),
486 CLKDEV_CON_ID("fsib_clk", &div6_clks[DIV6_FSIB]),
487 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
488 CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
489 CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
490 CLKDEV_CON_ID("hdmi_clk", &div6_reparent_clks[DIV6_HDMI]),
491 CLKDEV_CON_ID("dsit_clk", &div6_clks[DIV6_DSIT]),
492 CLKDEV_CON_ID("dsi0p_clk", &div6_clks[DIV6_DSI0P]),
493 CLKDEV_CON_ID("dsi1p_clk", &div6_clks[DIV6_DSI1P]),
494
495 /* MSTP32 clocks */
496 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
497 CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */
498 CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */
499 CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP129]), /* VEU1 */
500 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */
501 CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
502 CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */
503 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
504 CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */
505 CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */
506 CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
507 CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[MSTP223]), /* SPU2DSP0 */
508 CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[MSTP223]), /* SPU2DSP1 */
509 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
510 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP206]), /* SCIFB */
511 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
512 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
513 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
514 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
515 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
516 CLKDEV_CON_ID("cmt1", &mstp_clks[MSTP329]), /* CMT10 */
517 CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */
518 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
519 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP323]), /* USB0 */
520 CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP323]), /* USB0 */
521 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
522 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
523 CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */
524 CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), /* SDHI2 */
525 CLKDEV_DEV_ID("sh-mobile-hdmi", &mstp_clks[MSTP413]), /* HDMI */
526 CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* IIC3 */
527 CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */
528 CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */
529 CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */
530 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
531 {.con_id = "ick", .dev_id = "sh-mobile-hdmi", .clk = &div6_reparent_clks[DIV6_HDMI]},
532};
533
534void __init sh7372_clock_init(void)
535{
536 int k, ret = 0;
537
538 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
539 ret = clk_register(main_clks[k]);
540
541 if (!ret)
542 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
543
544 if (!ret)
545 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
546
547 if (!ret)
548 ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_NR);
549
550 if (!ret)
551 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
552
553 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
554
555 if (!ret)
556 clk_init();
557 else
558 panic("failed to setup sh7372 clocks\n");
559
560}
diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c
new file mode 100644
index 00000000000..e007c28cf0a
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-sh7377.c
@@ -0,0 +1,369 @@
1/*
2 * SH7377 clock framework support
3 *
4 * Copyright (C) 2010 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 as published by
8 * the Free Software Foundation; either version 2 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <linux/init.h>
20#include <linux/kernel.h>
21#include <linux/io.h>
22#include <linux/sh_clk.h>
23#include <mach/common.h>
24#include <asm/clkdev.h>
25
26/* SH7377 registers */
27#define RTFRQCR 0xe6150000
28#define SYFRQCR 0xe6150004
29#define CMFRQCR 0xe61500E0
30#define VCLKCR1 0xe6150008
31#define VCLKCR2 0xe615000C
32#define VCLKCR3 0xe615001C
33#define FMSICKCR 0xe6150010
34#define FMSOCKCR 0xe6150014
35#define FSICKCR 0xe6150018
36#define PLLC1CR 0xe6150028
37#define PLLC2CR 0xe615002C
38#define SUBUSBCKCR 0xe6150080
39#define SPUCKCR 0xe6150084
40#define MSUCKCR 0xe6150088
41#define MVI3CKCR 0xe6150090
42#define HDMICKCR 0xe6150094
43#define MFCK1CR 0xe6150098
44#define MFCK2CR 0xe615009C
45#define DSITCKCR 0xe6150060
46#define DSIPCKCR 0xe6150064
47#define SMSTPCR0 0xe6150130
48#define SMSTPCR1 0xe6150134
49#define SMSTPCR2 0xe6150138
50#define SMSTPCR3 0xe615013C
51#define SMSTPCR4 0xe6150140
52
53/* Fixed 32 KHz root clock from EXTALR pin */
54static struct clk r_clk = {
55 .rate = 32768,
56};
57
58/*
59 * 26MHz default rate for the EXTALC1 root input clock.
60 * If needed, reset this with clk_set_rate() from the platform code.
61 */
62struct clk sh7377_extalc1_clk = {
63 .rate = 26666666,
64};
65
66/*
67 * 48MHz default rate for the EXTAL2 root input clock.
68 * If needed, reset this with clk_set_rate() from the platform code.
69 */
70struct clk sh7377_extal2_clk = {
71 .rate = 48000000,
72};
73
74/* A fixed divide-by-2 block */
75static unsigned long div2_recalc(struct clk *clk)
76{
77 return clk->parent->rate / 2;
78}
79
80static struct clk_ops div2_clk_ops = {
81 .recalc = div2_recalc,
82};
83
84/* Divide extalc1 by two */
85static struct clk extalc1_div2_clk = {
86 .ops = &div2_clk_ops,
87 .parent = &sh7377_extalc1_clk,
88};
89
90/* Divide extal2 by two */
91static struct clk extal2_div2_clk = {
92 .ops = &div2_clk_ops,
93 .parent = &sh7377_extal2_clk,
94};
95
96/* Divide extal2 by four */
97static struct clk extal2_div4_clk = {
98 .ops = &div2_clk_ops,
99 .parent = &extal2_div2_clk,
100};
101
102/* PLLC1 */
103static unsigned long pllc1_recalc(struct clk *clk)
104{
105 unsigned long mult = 1;
106
107 if (__raw_readl(PLLC1CR) & (1 << 14))
108 mult = (((__raw_readl(RTFRQCR) >> 24) & 0x3f) + 1) * 2;
109
110 return clk->parent->rate * mult;
111}
112
113static struct clk_ops pllc1_clk_ops = {
114 .recalc = pllc1_recalc,
115};
116
117static struct clk pllc1_clk = {
118 .ops = &pllc1_clk_ops,
119 .flags = CLK_ENABLE_ON_INIT,
120 .parent = &extalc1_div2_clk,
121};
122
123/* Divide PLLC1 by two */
124static struct clk pllc1_div2_clk = {
125 .ops = &div2_clk_ops,
126 .parent = &pllc1_clk,
127};
128
129/* PLLC2 */
130static unsigned long pllc2_recalc(struct clk *clk)
131{
132 unsigned long mult = 1;
133
134 if (__raw_readl(PLLC2CR) & (1 << 31))
135 mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2;
136
137 return clk->parent->rate * mult;
138}
139
140static struct clk_ops pllc2_clk_ops = {
141 .recalc = pllc2_recalc,
142};
143
144static struct clk pllc2_clk = {
145 .ops = &pllc2_clk_ops,
146 .flags = CLK_ENABLE_ON_INIT,
147 .parent = &extalc1_div2_clk,
148};
149
150static struct clk *main_clks[] = {
151 &r_clk,
152 &sh7377_extalc1_clk,
153 &sh7377_extal2_clk,
154 &extalc1_div2_clk,
155 &extal2_div2_clk,
156 &extal2_div4_clk,
157 &pllc1_clk,
158 &pllc1_div2_clk,
159 &pllc2_clk,
160};
161
162static void div4_kick(struct clk *clk)
163{
164 unsigned long value;
165
166 /* set KICK bit in SYFRQCR to update hardware setting */
167 value = __raw_readl(SYFRQCR);
168 value |= (1 << 31);
169 __raw_writel(value, SYFRQCR);
170}
171
172static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
173 24, 32, 36, 48, 0, 72, 96, 0 };
174
175static struct clk_div_mult_table div4_div_mult_table = {
176 .divisors = divisors,
177 .nr_divisors = ARRAY_SIZE(divisors),
178};
179
180static struct clk_div4_table div4_table = {
181 .div_mult_table = &div4_div_mult_table,
182 .kick = div4_kick,
183};
184
185enum { DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_CSIR,
186 DIV4_ZTR, DIV4_ZT, DIV4_Z, DIV4_HP,
187 DIV4_ZS, DIV4_ZB, DIV4_ZB3, DIV4_CP, DIV4_NR };
188
189#define DIV4(_reg, _bit, _mask, _flags) \
190 SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
191
192static struct clk div4_clks[DIV4_NR] = {
193 [DIV4_I] = DIV4(RTFRQCR, 20, 0x6fff, CLK_ENABLE_ON_INIT),
194 [DIV4_ZG] = DIV4(RTFRQCR, 16, 0x6fff, CLK_ENABLE_ON_INIT),
195 [DIV4_B] = DIV4(RTFRQCR, 8, 0x6fff, CLK_ENABLE_ON_INIT),
196 [DIV4_M1] = DIV4(RTFRQCR, 4, 0x6fff, CLK_ENABLE_ON_INIT),
197 [DIV4_CSIR] = DIV4(RTFRQCR, 0, 0x6fff, 0),
198 [DIV4_ZTR] = DIV4(SYFRQCR, 20, 0x6fff, 0),
199 [DIV4_ZT] = DIV4(SYFRQCR, 16, 0x6fff, 0),
200 [DIV4_Z] = DIV4(SYFRQCR, 12, 0x6fff, 0),
201 [DIV4_HP] = DIV4(SYFRQCR, 4, 0x6fff, 0),
202 [DIV4_ZS] = DIV4(CMFRQCR, 12, 0x6fff, 0),
203 [DIV4_ZB] = DIV4(CMFRQCR, 8, 0x6fff, 0),
204 [DIV4_ZB3] = DIV4(CMFRQCR, 4, 0x6fff, 0),
205 [DIV4_CP] = DIV4(CMFRQCR, 0, 0x6fff, 0),
206};
207
208enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO,
209 DIV6_FSI, DIV6_SUB, DIV6_SPU, DIV6_MSU, DIV6_MVI3, DIV6_HDMI,
210 DIV6_MF1, DIV6_MF2, DIV6_DSIT, DIV6_DSIP,
211 DIV6_NR };
212
213static struct clk div6_clks[] = {
214 [DIV6_VCK1] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR1, 0),
215 [DIV6_VCK2] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR2, 0),
216 [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0),
217 [DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0),
218 [DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0),
219 [DIV6_FSI] = SH_CLK_DIV6(&pllc1_div2_clk, FSICKCR, 0),
220 [DIV6_SUB] = SH_CLK_DIV6(&sh7377_extal2_clk, SUBUSBCKCR, 0),
221 [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0),
222 [DIV6_MSU] = SH_CLK_DIV6(&pllc1_div2_clk, MSUCKCR, 0),
223 [DIV6_MVI3] = SH_CLK_DIV6(&pllc1_div2_clk, MVI3CKCR, 0),
224 [DIV6_HDMI] = SH_CLK_DIV6(&pllc1_div2_clk, HDMICKCR, 0),
225 [DIV6_MF1] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK1CR, 0),
226 [DIV6_MF2] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK2CR, 0),
227 [DIV6_DSIT] = SH_CLK_DIV6(&pllc1_div2_clk, DSITCKCR, 0),
228 [DIV6_DSIP] = SH_CLK_DIV6(&pllc1_div2_clk, DSIPCKCR, 0),
229};
230
231enum { MSTP001,
232 MSTP131, MSTP130, MSTP129, MSTP128, MSTP116, MSTP106, MSTP101,
233 MSTP223, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
234 MSTP331, MSTP329, MSTP325, MSTP323, MSTP322,
235 MSTP315, MSTP314, MSTP313,
236 MSTP403,
237 MSTP_NR };
238
239#define MSTP(_parent, _reg, _bit, _flags) \
240 SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
241
242static struct clk mstp_clks[] = {
243 [MSTP001] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR0, 1, 0), /* IIC2 */
244 [MSTP131] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 31, 0), /* VEU3 */
245 [MSTP130] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 30, 0), /* VEU2 */
246 [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* VEU1 */
247 [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */
248 [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
249 [MSTP106] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 6, 0), /* JPU */
250 [MSTP101] = MSTP(&div4_clks[DIV4_M1], SMSTPCR1, 1, 0), /* VPU */
251 [MSTP223] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR2, 23, 0), /* SPU2 */
252 [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
253 [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
254 [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
255 [MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
256 [MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
257 [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
258 [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
259 [MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */
260 [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
261 [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IRDA */
262 [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
263 [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */
264 [MSTP315] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 15, 0), /* FLCTL */
265 [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
266 [MSTP313] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
267 [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
268};
269
270#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
271#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
272
273static struct clk_lookup lookups[] = {
274 /* main clocks */
275 CLKDEV_CON_ID("r_clk", &r_clk),
276 CLKDEV_CON_ID("extalc1", &sh7377_extalc1_clk),
277 CLKDEV_CON_ID("extal2", &sh7377_extal2_clk),
278 CLKDEV_CON_ID("extalc1_div2_clk", &extalc1_div2_clk),
279 CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk),
280 CLKDEV_CON_ID("extal2_div4_clk", &extal2_div4_clk),
281 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
282 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
283 CLKDEV_CON_ID("pllc2_clk", &pllc2_clk),
284
285 /* DIV4 clocks */
286 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
287 CLKDEV_CON_ID("zg_clk", &div4_clks[DIV4_ZG]),
288 CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
289 CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]),
290 CLKDEV_CON_ID("csir_clk", &div4_clks[DIV4_CSIR]),
291 CLKDEV_CON_ID("ztr_clk", &div4_clks[DIV4_ZTR]),
292 CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]),
293 CLKDEV_CON_ID("z_clk", &div4_clks[DIV4_Z]),
294 CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
295 CLKDEV_CON_ID("zs_clk", &div4_clks[DIV4_ZS]),
296 CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
297 CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]),
298 CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
299
300 /* DIV6 clocks */
301 CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
302 CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
303 CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
304 CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]),
305 CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]),
306 CLKDEV_CON_ID("fsi_clk", &div6_clks[DIV6_FSI]),
307 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
308 CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
309 CLKDEV_CON_ID("msu_clk", &div6_clks[DIV6_MSU]),
310 CLKDEV_CON_ID("mvi3_clk", &div6_clks[DIV6_MVI3]),
311 CLKDEV_CON_ID("hdmi_clk", &div6_clks[DIV6_HDMI]),
312 CLKDEV_CON_ID("mf1_clk", &div6_clks[DIV6_MF1]),
313 CLKDEV_CON_ID("mf2_clk", &div6_clks[DIV6_MF2]),
314 CLKDEV_CON_ID("dsit_clk", &div6_clks[DIV6_DSIT]),
315 CLKDEV_CON_ID("dsip_clk", &div6_clks[DIV6_DSIP]),
316
317 /* MSTP32 clocks */
318 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
319 CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */
320 CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */
321 CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP129]), /* VEU1 */
322 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */
323 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
324 CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */
325 CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */
326 CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[MSTP223]), /* SPU2DSP0 */
327 CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[MSTP223]), /* SPU2DSP1 */
328 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
329 CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP206]), /* SCIFB */
330 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
331 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
332 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
333 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
334 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
335 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
336 CLKDEV_CON_ID("cmt1", &mstp_clks[MSTP329]), /* CMT10 */
337 CLKDEV_DEV_ID("sh_irda", &mstp_clks[MSTP325]), /* IRDA */
338 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
339 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USBHS */
340 CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USBHS */
341 CLKDEV_DEV_ID("sh_flctl", &mstp_clks[MSTP315]), /* FLCTL */
342 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
343 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
344 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
345};
346
347void __init sh7377_clock_init(void)
348{
349 int k, ret = 0;
350
351 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
352 ret = clk_register(main_clks[k]);
353
354 if (!ret)
355 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
356
357 if (!ret)
358 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
359
360 if (!ret)
361 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
362
363 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
364
365 if (!ret)
366 clk_init();
367 else
368 panic("failed to setup sh7377 clocks\n");
369}
diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
new file mode 100644
index 00000000000..b7c705a213a
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock.c
@@ -0,0 +1,44 @@
1/*
2 * SH-Mobile Timer
3 *
4 * Copyright (C) 2010 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 as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/sh_clk.h>
23
24int __init clk_init(void)
25{
26 /* Kick the child clocks.. */
27 recalculate_root_clocks();
28
29 /* Enable the necessary init clocks */
30 clk_enable_init_clocks();
31
32 return 0;
33}
34
35int __clk_get(struct clk *clk)
36{
37 return 1;
38}
39EXPORT_SYMBOL(__clk_get);
40
41void __clk_put(struct clk *clk)
42{
43}
44EXPORT_SYMBOL(__clk_put);
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 57903605cc5..efeef778a87 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -3,21 +3,31 @@
3 3
4extern struct sys_timer shmobile_timer; 4extern struct sys_timer shmobile_timer;
5extern void shmobile_setup_console(void); 5extern void shmobile_setup_console(void);
6struct clk;
7extern int clk_init(void);
6 8
7extern void sh7367_init_irq(void); 9extern void sh7367_init_irq(void);
8extern void sh7367_add_early_devices(void); 10extern void sh7367_add_early_devices(void);
9extern void sh7367_add_standard_devices(void); 11extern void sh7367_add_standard_devices(void);
10extern void sh7367_clock_init(void); 12extern void sh7367_clock_init(void);
11extern void sh7367_pinmux_init(void); 13extern void sh7367_pinmux_init(void);
14extern struct clk sh7367_extalb1_clk;
15extern struct clk sh7367_extal2_clk;
12 16
13extern void sh7377_init_irq(void); 17extern void sh7377_init_irq(void);
14extern void sh7377_add_early_devices(void); 18extern void sh7377_add_early_devices(void);
15extern void sh7377_add_standard_devices(void); 19extern void sh7377_add_standard_devices(void);
20extern void sh7377_clock_init(void);
16extern void sh7377_pinmux_init(void); 21extern void sh7377_pinmux_init(void);
22extern struct clk sh7377_extalc1_clk;
23extern struct clk sh7377_extal2_clk;
17 24
18extern void sh7372_init_irq(void); 25extern void sh7372_init_irq(void);
19extern void sh7372_add_early_devices(void); 26extern void sh7372_add_early_devices(void);
20extern void sh7372_add_standard_devices(void); 27extern void sh7372_add_standard_devices(void);
28extern void sh7372_clock_init(void);
21extern void sh7372_pinmux_init(void); 29extern void sh7372_pinmux_init(void);
30extern struct clk sh7372_extal1_clk;
31extern struct clk sh7372_extal2_clk;
22 32
23#endif /* __ARCH_MACH_COMMON_H */ 33#endif /* __ARCH_MACH_COMMON_H */
diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
index 132256bb8c8..fa15b5f8a00 100644
--- a/arch/arm/mach-shmobile/include/mach/irqs.h
+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
@@ -3,7 +3,13 @@
3 3
4#define NR_IRQS 512 4#define NR_IRQS 512
5 5
6/* INTCA */
6#define evt2irq(evt) (((evt) >> 5) - 16) 7#define evt2irq(evt) (((evt) >> 5) - 16)
7#define irq2evt(irq) (((irq) + 16) << 5) 8#define irq2evt(irq) (((irq) + 16) << 5)
8 9
10/* INTCS */
11#define INTCS_VECT_BASE 0x2200
12#define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect))
13#define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt))
14
9#endif /* __ASM_MACH_IRQS_H */ 15#endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-shmobile/include/mach/memory.h b/arch/arm/mach-shmobile/include/mach/memory.h
index e188183f4dc..377584e57e0 100644
--- a/arch/arm/mach-shmobile/include/mach/memory.h
+++ b/arch/arm/mach-shmobile/include/mach/memory.h
@@ -4,4 +4,7 @@
4#define PHYS_OFFSET UL(CONFIG_MEMORY_START) 4#define PHYS_OFFSET UL(CONFIG_MEMORY_START)
5#define MEM_SIZE UL(CONFIG_MEMORY_SIZE) 5#define MEM_SIZE UL(CONFIG_MEMORY_SIZE)
6 6
7/* DMA memory at 0xf6000000 - 0xffdfffff */
8#define CONSISTENT_DMA_SIZE (158 << 20)
9
7#endif /* __ASM_MACH_MEMORY_H */ 10#endif /* __ASM_MACH_MEMORY_H */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index dc34f00c56b..33e9700ded7 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -11,6 +11,8 @@
11#ifndef __ASM_SH7372_H__ 11#ifndef __ASM_SH7372_H__
12#define __ASM_SH7372_H__ 12#define __ASM_SH7372_H__
13 13
14#include <linux/sh_clk.h>
15
14/* 16/*
15 * Pin Function Controller: 17 * Pin Function Controller:
16 * GPIO_FN_xx - GPIO used to select pin function 18 * GPIO_FN_xx - GPIO used to select pin function
@@ -431,4 +433,32 @@ enum {
431 GPIO_FN_SDENC_DV_CLKI, 433 GPIO_FN_SDENC_DV_CLKI,
432}; 434};
433 435
436/* DMA slave IDs */
437enum {
438 SHDMA_SLAVE_SCIF0_TX,
439 SHDMA_SLAVE_SCIF0_RX,
440 SHDMA_SLAVE_SCIF1_TX,
441 SHDMA_SLAVE_SCIF1_RX,
442 SHDMA_SLAVE_SCIF2_TX,
443 SHDMA_SLAVE_SCIF2_RX,
444 SHDMA_SLAVE_SCIF3_TX,
445 SHDMA_SLAVE_SCIF3_RX,
446 SHDMA_SLAVE_SCIF4_TX,
447 SHDMA_SLAVE_SCIF4_RX,
448 SHDMA_SLAVE_SCIF5_TX,
449 SHDMA_SLAVE_SCIF5_RX,
450 SHDMA_SLAVE_SCIF6_TX,
451 SHDMA_SLAVE_SCIF6_RX,
452 SHDMA_SLAVE_SDHI0_RX,
453 SHDMA_SLAVE_SDHI0_TX,
454 SHDMA_SLAVE_SDHI1_RX,
455 SHDMA_SLAVE_SDHI1_TX,
456 SHDMA_SLAVE_SDHI2_RX,
457 SHDMA_SLAVE_SDHI2_TX,
458};
459
460extern struct clk dv_clki_clk;
461extern struct clk dv_clki_div2_clk;
462extern struct clk pllc2_clk;
463
434#endif /* __ASM_SH7372_H__ */ 464#endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/vmalloc.h b/arch/arm/mach-shmobile/include/mach/vmalloc.h
index fb3c4f1ab25..4aecf6e3a85 100644
--- a/arch/arm/mach-shmobile/include/mach/vmalloc.h
+++ b/arch/arm/mach-shmobile/include/mach/vmalloc.h
@@ -1,6 +1,7 @@
1#ifndef __ASM_MACH_VMALLOC_H 1#ifndef __ASM_MACH_VMALLOC_H
2#define __ASM_MACH_VMALLOC_H 2#define __ASM_MACH_VMALLOC_H
3 3
4#define VMALLOC_END (PAGE_OFFSET + 0x24000000) 4/* Vmalloc at ... - 0xe5ffffff */
5#define VMALLOC_END 0xe6000000
5 6
6#endif /* __ASM_MACH_VMALLOC_H */ 7#endif /* __ASM_MACH_VMALLOC_H */
diff --git a/arch/arm/mach-shmobile/intc-sh7367.c b/arch/arm/mach-shmobile/intc-sh7367.c
index 5ff70cadfc3..1a20c489b20 100644
--- a/arch/arm/mach-shmobile/intc-sh7367.c
+++ b/arch/arm/mach-shmobile/intc-sh7367.c
@@ -75,7 +75,7 @@ enum {
75 ETM11, ARM11, USBHS, FLCTL, IIC1 75 ETM11, ARM11, USBHS, FLCTL, IIC1
76}; 76};
77 77
78static struct intc_vect intca_vectors[] = { 78static struct intc_vect intca_vectors[] __initdata = {
79 INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220), 79 INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
80 INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260), 80 INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
81 INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0), 81 INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
@@ -162,7 +162,7 @@ static struct intc_group intca_groups[] __initdata = {
162 INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1), 162 INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1),
163}; 163};
164 164
165static struct intc_mask_reg intca_mask_registers[] = { 165static struct intc_mask_reg intca_mask_registers[] __initdata = {
166 { 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */ 166 { 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
167 { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } }, 167 { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
168 { 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */ 168 { 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
@@ -211,7 +211,7 @@ static struct intc_mask_reg intca_mask_registers[] = {
211 MISTY, CMT3, RWDT1, RWDT0 } }, 211 MISTY, CMT3, RWDT1, RWDT0 } },
212}; 212};
213 213
214static struct intc_prio_reg intca_prio_registers[] = { 214static struct intc_prio_reg intca_prio_registers[] __initdata = {
215 { 0xe6900010, 0, 32, 4, /* INTPRI00A */ 215 { 0xe6900010, 0, 32, 4, /* INTPRI00A */
216 { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } }, 216 { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
217 { 0xe6900014, 0, 32, 4, /* INTPRI10A */ 217 { 0xe6900014, 0, 32, 4, /* INTPRI10A */
@@ -263,8 +263,178 @@ static struct intc_desc intca_desc __initdata = {
263 intca_sense_registers, intca_ack_registers), 263 intca_sense_registers, intca_ack_registers),
264}; 264};
265 265
266enum {
267 UNUSED_INTCS = 0,
268
269 INTCS,
270
271 /* interrupt sources INTCS */
272 VIO2_VEU0, VIO2_VEU1, VIO2_VEU2, VIO2_VEU3,
273 VIO3_VOU,
274 RTDMAC_1_DEI0, RTDMAC_1_DEI1, RTDMAC_1_DEI2, RTDMAC_1_DEI3,
275 VIO1_CEU, VIO1_BEU0, VIO1_BEU1, VIO1_BEU2,
276 VPU,
277 SGX530,
278 _2DDMAC_2DDM0, _2DDMAC_2DDM1, _2DDMAC_2DDM2, _2DDMAC_2DDM3,
279 IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2,
280 IPMMU_IPMMUB, IPMMU_IPMMUS,
281 RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR,
282 MSIOF,
283 IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0,
284 TMU_TUNI0, TMU_TUNI1, TMU_TUNI2,
285 CMT,
286 TSIF,
287 IPMMUI,
288 MVI3,
289 ICB,
290 PEP,
291 ASA,
292 BEM,
293 VE2HO,
294 HQE,
295 JPEG,
296 LCDC,
297
298 /* interrupt groups INTCS */
299 _2DDMAC, RTDMAC_1, RTDMAC_2, VEU, BEU, IIC0, IPMMU, IIC2,
300};
301
302static struct intc_vect intcs_vectors[] = {
303 INTCS_VECT(VIO2_VEU0, 0x700), INTCS_VECT(VIO2_VEU1, 0x720),
304 INTCS_VECT(VIO2_VEU2, 0x740), INTCS_VECT(VIO2_VEU3, 0x760),
305 INTCS_VECT(VIO3_VOU, 0x780),
306 INTCS_VECT(RTDMAC_1_DEI0, 0x800), INTCS_VECT(RTDMAC_1_DEI1, 0x820),
307 INTCS_VECT(RTDMAC_1_DEI2, 0x840), INTCS_VECT(RTDMAC_1_DEI3, 0x860),
308 INTCS_VECT(VIO1_CEU, 0x880), INTCS_VECT(VIO1_BEU0, 0x8a0),
309 INTCS_VECT(VIO1_BEU1, 0x8c0), INTCS_VECT(VIO1_BEU2, 0x8e0),
310 INTCS_VECT(VPU, 0x980),
311 INTCS_VECT(SGX530, 0x9e0),
312 INTCS_VECT(_2DDMAC_2DDM0, 0xa00), INTCS_VECT(_2DDMAC_2DDM1, 0xa20),
313 INTCS_VECT(_2DDMAC_2DDM2, 0xa40), INTCS_VECT(_2DDMAC_2DDM3, 0xa60),
314 INTCS_VECT(IIC2_ALI2, 0xa80), INTCS_VECT(IIC2_TACKI2, 0xaa0),
315 INTCS_VECT(IIC2_WAITI2, 0xac0), INTCS_VECT(IIC2_DTEI2, 0xae0),
316 INTCS_VECT(IPMMU_IPMMUB, 0xb20), INTCS_VECT(IPMMU_IPMMUS, 0xb60),
317 INTCS_VECT(RTDMAC_2_DEI4, 0xb80), INTCS_VECT(RTDMAC_2_DEI5, 0xba0),
318 INTCS_VECT(RTDMAC_2_DADERR, 0xbc0),
319 INTCS_VECT(MSIOF, 0xd20),
320 INTCS_VECT(IIC0_ALI0, 0xe00), INTCS_VECT(IIC0_TACKI0, 0xe20),
321 INTCS_VECT(IIC0_WAITI0, 0xe40), INTCS_VECT(IIC0_DTEI0, 0xe60),
322 INTCS_VECT(TMU_TUNI0, 0xe80), INTCS_VECT(TMU_TUNI1, 0xea0),
323 INTCS_VECT(TMU_TUNI2, 0xec0),
324 INTCS_VECT(CMT, 0xf00),
325 INTCS_VECT(TSIF, 0xf20),
326 INTCS_VECT(IPMMUI, 0xf60),
327 INTCS_VECT(MVI3, 0x420),
328 INTCS_VECT(ICB, 0x480),
329 INTCS_VECT(PEP, 0x4a0),
330 INTCS_VECT(ASA, 0x4c0),
331 INTCS_VECT(BEM, 0x4e0),
332 INTCS_VECT(VE2HO, 0x520),
333 INTCS_VECT(HQE, 0x540),
334 INTCS_VECT(JPEG, 0x560),
335 INTCS_VECT(LCDC, 0x580),
336
337 INTC_VECT(INTCS, 0xf80),
338};
339
340static struct intc_group intcs_groups[] __initdata = {
341 INTC_GROUP(_2DDMAC, _2DDMAC_2DDM0, _2DDMAC_2DDM1,
342 _2DDMAC_2DDM2, _2DDMAC_2DDM3),
343 INTC_GROUP(RTDMAC_1, RTDMAC_1_DEI0, RTDMAC_1_DEI1,
344 RTDMAC_1_DEI2, RTDMAC_1_DEI3),
345 INTC_GROUP(RTDMAC_2, RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR),
346 INTC_GROUP(VEU, VIO2_VEU0, VIO2_VEU1, VIO2_VEU2, VIO2_VEU3),
347 INTC_GROUP(BEU, VIO1_BEU0, VIO1_BEU1, VIO1_BEU2),
348 INTC_GROUP(IIC0, IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0),
349 INTC_GROUP(IPMMU, IPMMU_IPMMUS, IPMMU_IPMMUB),
350 INTC_GROUP(IIC2, IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2),
351};
352
353static struct intc_mask_reg intcs_mask_registers[] = {
354 { 0xffd20184, 0xffd201c4, 8, /* IMR1SA / IMCR1SA */
355 { VIO1_BEU2, VIO1_BEU1, VIO1_BEU0, VIO1_CEU,
356 VIO2_VEU3, VIO2_VEU2, VIO2_VEU1, VIO2_VEU0 } },
357 { 0xffd20188, 0xffd201c8, 8, /* IMR2SA / IMCR2SA */
358 { VIO3_VOU, 0, VE2HO, VPU,
359 0, 0, 0, 0 } },
360 { 0xffd2018c, 0xffd201cc, 8, /* IMR3SA / IMCR3SA */
361 { _2DDMAC_2DDM3, _2DDMAC_2DDM2, _2DDMAC_2DDM1, _2DDMAC_2DDM0,
362 BEM, ASA, PEP, ICB } },
363 { 0xffd20190, 0xffd201d0, 8, /* IMR4SA / IMCR4SA */
364 { 0, 0, MVI3, 0,
365 JPEG, HQE, 0, LCDC } },
366 { 0xffd20194, 0xffd201d4, 8, /* IMR5SA / IMCR5SA */
367 { 0, RTDMAC_2_DADERR, RTDMAC_2_DEI5, RTDMAC_2_DEI4,
368 RTDMAC_1_DEI3, RTDMAC_1_DEI2, RTDMAC_1_DEI1, RTDMAC_1_DEI0 } },
369 { 0xffd20198, 0xffd201d8, 8, /* IMR6SA / IMCR6SA */
370 { 0, 0, MSIOF, 0,
371 SGX530, 0, 0, 0 } },
372 { 0xffd2019c, 0xffd201dc, 8, /* IMR7SA / IMCR7SA */
373 { 0, TMU_TUNI2, TMU_TUNI1, TMU_TUNI0,
374 0, 0, 0, 0 } },
375 { 0xffd201a4, 0xffd201e4, 8, /* IMR9SA / IMCR9SA */
376 { 0, 0, 0, CMT,
377 IIC2_DTEI2, IIC2_WAITI2, IIC2_TACKI2, IIC2_ALI2 } },
378 { 0xffd201a8, 0xffd201e8, 8, /* IMR10SA / IMCR10SA */
379 { IPMMU_IPMMUS, 0, IPMMU_IPMMUB, 0,
380 0, 0, 0, 0 } },
381 { 0xffd201ac, 0xffd201ec, 8, /* IMR11SA / IMCR11SA */
382 { IIC0_DTEI0, IIC0_WAITI0, IIC0_TACKI0, IIC0_ALI0,
383 0, 0, IPMMUI, TSIF } },
384 { 0xffd20104, 0, 16, /* INTAMASK */
385 { 0, 0, 0, 0, 0, 0, 0, 0,
386 0, 0, 0, 0, 0, 0, 0, INTCS } },
387};
388
389/* Priority is needed for INTCA to receive the INTCS interrupt */
390static struct intc_prio_reg intcs_prio_registers[] = {
391 { 0xffd20000, 0, 16, 4, /* IPRAS */ { 0, MVI3, _2DDMAC, ICB } },
392 { 0xffd20004, 0, 16, 4, /* IPRBS */ { JPEG, LCDC, 0, 0 } },
393 { 0xffd20008, 0, 16, 4, /* IPRCS */ { BBIF2, 0, 0, 0 } },
394 { 0xffd20010, 0, 16, 4, /* IPRES */ { RTDMAC_1, VIO1_CEU, 0, VPU } },
395 { 0xffd20014, 0, 16, 4, /* IPRFS */ { 0, RTDMAC_2, 0, CMT } },
396 { 0xffd20018, 0, 16, 4, /* IPRGS */ { TMU_TUNI0, TMU_TUNI1,
397 TMU_TUNI2, 0 } },
398 { 0xffd2001c, 0, 16, 4, /* IPRHS */ { 0, VIO3_VOU, VEU, BEU } },
399 { 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, MSIOF, TSIF, IIC0 } },
400 { 0xffd20024, 0, 16, 4, /* IPRJS */ { 0, SGX530, 0, 0 } },
401 { 0xffd20028, 0, 16, 4, /* IPRKS */ { BEM, ASA, IPMMUI, PEP } },
402 { 0xffd2002c, 0, 16, 4, /* IPRLS */ { IPMMU, 0, VE2HO, HQE } },
403 { 0xffd20030, 0, 16, 4, /* IPRMS */ { IIC2, 0, 0, 0 } },
404};
405
406static struct resource intcs_resources[] __initdata = {
407 [0] = {
408 .start = 0xffd20000,
409 .end = 0xffd2ffff,
410 .flags = IORESOURCE_MEM,
411 }
412};
413
414static struct intc_desc intcs_desc __initdata = {
415 .name = "sh7367-intcs",
416 .resource = intcs_resources,
417 .num_resources = ARRAY_SIZE(intcs_resources),
418 .hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
419 intcs_prio_registers, NULL, NULL),
420};
421
422static void intcs_demux(unsigned int irq, struct irq_desc *desc)
423{
424 void __iomem *reg = (void *)get_irq_data(irq);
425 unsigned int evtcodeas = ioread32(reg);
426
427 generic_handle_irq(intcs_evt2irq(evtcodeas));
428}
429
266void __init sh7367_init_irq(void) 430void __init sh7367_init_irq(void)
267{ 431{
268 /* INTCA */ 432 void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
433
269 register_intc_controller(&intca_desc); 434 register_intc_controller(&intca_desc);
435 register_intc_controller(&intcs_desc);
436
437 /* demux using INTEVTSA */
438 set_irq_data(evt2irq(0xf80), (void *)intevtsa);
439 set_irq_chained_handler(evt2irq(0xf80), intcs_demux);
270} 440}
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
index 3ce9d9bd589..e3551b56cd0 100644
--- a/arch/arm/mach-shmobile/intc-sh7372.c
+++ b/arch/arm/mach-shmobile/intc-sh7372.c
@@ -319,17 +319,17 @@ static struct intc_prio_reg intca_prio_registers[] __initdata = {
319 { 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } }, 319 { 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } },
320 { 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S, 320 { 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S,
321 CMT14, CMT15 } }, 321 CMT14, CMT15 } },
322 { 0xe694003c, 0, 16, 4, /* IPRPA3 */ { 0, 0, 322 { 0xe695003c, 0, 16, 4, /* IPRPA3 */ { 0, 0,
323 MMC_MMC_ERR, MMC_MMC_NOR } }, 323 MMC_MMC_ERR, MMC_MMC_NOR } },
324 { 0xe6940040, 0, 16, 4, /* IPRQA3 */ { IIC4_ALI4, IIC4_TACKI4, 324 { 0xe6950040, 0, 16, 4, /* IPRQA3 */ { IIC4_ALI4, IIC4_TACKI4,
325 IIC4_WAITI4, IIC4_DTEI4 } }, 325 IIC4_WAITI4, IIC4_DTEI4 } },
326 { 0xe6940044, 0, 16, 4, /* IPRRA3 */ { IIC3_ALI3, IIC3_TACKI3, 326 { 0xe6950044, 0, 16, 4, /* IPRRA3 */ { IIC3_ALI3, IIC3_TACKI3,
327 IIC3_WAITI3, IIC3_DTEI3 } }, 327 IIC3_WAITI3, IIC3_DTEI3 } },
328 { 0xe6940048, 0, 16, 4, /* IPRSA3 */ { 0/*ERI*/, 0/*RXI*/, 328 { 0xe6950048, 0, 16, 4, /* IPRSA3 */ { 0/*ERI*/, 0/*RXI*/,
329 0/*TXI*/, 0/*TEI*/} }, 329 0/*TXI*/, 0/*TEI*/} },
330 { 0xe694004c, 0, 16, 4, /* IPRTA3 */ { USB0_USB0I1, USB0_USB0I0, 330 { 0xe695004c, 0, 16, 4, /* IPRTA3 */ { USB0_USB0I1, USB0_USB0I0,
331 USB1_USB1I1, USB1_USB1I0 } }, 331 USB1_USB1I1, USB1_USB1I0 } },
332 { 0xe6940050, 0, 16, 4, /* IPRUA3 */ { USBHSDMAC1_USHDMI, 0, 0, 0 } }, 332 { 0xe6950050, 0, 16, 4, /* IPRUA3 */ { USBHSDMAC1_USHDMI, 0, 0, 0 } },
333}; 333};
334 334
335static struct intc_sense_reg intca_sense_registers[] __initdata = { 335static struct intc_sense_reg intca_sense_registers[] __initdata = {
@@ -363,7 +363,227 @@ static struct intc_desc intca_desc __initdata = {
363 intca_sense_registers, intca_ack_registers), 363 intca_sense_registers, intca_ack_registers),
364}; 364};
365 365
366enum {
367 UNUSED_INTCS = 0,
368
369 INTCS,
370
371 /* interrupt sources INTCS */
372 VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3,
373 RTDMAC_1_DEI0, RTDMAC_1_DEI1, RTDMAC_1_DEI2, RTDMAC_1_DEI3,
374 CEU, BEU_BEU0, BEU_BEU1, BEU_BEU2,
375 VPU,
376 TSIF1,
377 _3DG_SGX530,
378 _2DDMAC,
379 IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2,
380 IPMMU_IPMMUR, IPMMU_IPMMUR2,
381 RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR,
382 MSIOF,
383 IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0,
384 TMU_TUNI0, TMU_TUNI1, TMU_TUNI2,
385 CMT0,
386 TSIF0,
387 LMB,
388 CTI,
389 ICB,
390 JPU_JPEG,
391 LCDC,
392 LCRC,
393 RTDMAC2_1_DEI0, RTDMAC2_1_DEI1, RTDMAC2_1_DEI2, RTDMAC2_1_DEI3,
394 RTDMAC2_2_DEI4, RTDMAC2_2_DEI5, RTDMAC2_2_DADERR,
395 ISP,
396 LCDC1,
397 CSIRX,
398 DSITX_DSITX0,
399 DSITX_DSITX1,
400 TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2,
401 CMT4,
402 DSITX1_DSITX1_0,
403 DSITX1_DSITX1_1,
404 CPORTS2R,
405 JPU6E,
406
407 /* interrupt groups INTCS */
408 RTDMAC_1, RTDMAC_2, VEU, BEU, IIC0, IPMMU, IIC2,
409 RTDMAC2_1, RTDMAC2_2, TMU1, DSITX,
410};
411
412static struct intc_vect intcs_vectors[] = {
413 INTCS_VECT(VEU_VEU0, 0x700), INTCS_VECT(VEU_VEU1, 0x720),
414 INTCS_VECT(VEU_VEU2, 0x740), INTCS_VECT(VEU_VEU3, 0x760),
415 INTCS_VECT(RTDMAC_1_DEI0, 0x800), INTCS_VECT(RTDMAC_1_DEI1, 0x820),
416 INTCS_VECT(RTDMAC_1_DEI2, 0x840), INTCS_VECT(RTDMAC_1_DEI3, 0x860),
417 INTCS_VECT(CEU, 0x880), INTCS_VECT(BEU_BEU0, 0x8a0),
418 INTCS_VECT(BEU_BEU1, 0x8c0), INTCS_VECT(BEU_BEU2, 0x8e0),
419 INTCS_VECT(VPU, 0x980),
420 INTCS_VECT(TSIF1, 0x9a0),
421 INTCS_VECT(_3DG_SGX530, 0x9e0),
422 INTCS_VECT(_2DDMAC, 0xa00),
423 INTCS_VECT(IIC2_ALI2, 0xa80), INTCS_VECT(IIC2_TACKI2, 0xaa0),
424 INTCS_VECT(IIC2_WAITI2, 0xac0), INTCS_VECT(IIC2_DTEI2, 0xae0),
425 INTCS_VECT(IPMMU_IPMMUR, 0xb00), INTCS_VECT(IPMMU_IPMMUR2, 0xb20),
426 INTCS_VECT(RTDMAC_2_DEI4, 0xb80), INTCS_VECT(RTDMAC_2_DEI5, 0xba0),
427 INTCS_VECT(RTDMAC_2_DADERR, 0xbc0),
428 INTCS_VECT(IIC0_ALI0, 0xe00), INTCS_VECT(IIC0_TACKI0, 0xe20),
429 INTCS_VECT(IIC0_WAITI0, 0xe40), INTCS_VECT(IIC0_DTEI0, 0xe60),
430 INTCS_VECT(TMU_TUNI0, 0xe80), INTCS_VECT(TMU_TUNI1, 0xea0),
431 INTCS_VECT(TMU_TUNI2, 0xec0),
432 INTCS_VECT(CMT0, 0xf00),
433 INTCS_VECT(TSIF0, 0xf20),
434 INTCS_VECT(LMB, 0xf60),
435 INTCS_VECT(CTI, 0x400),
436 INTCS_VECT(ICB, 0x480),
437 INTCS_VECT(JPU_JPEG, 0x560),
438 INTCS_VECT(LCDC, 0x580),
439 INTCS_VECT(LCRC, 0x5a0),
440 INTCS_VECT(RTDMAC2_1_DEI0, 0x1300), INTCS_VECT(RTDMAC2_1_DEI1, 0x1320),
441 INTCS_VECT(RTDMAC2_1_DEI2, 0x1340), INTCS_VECT(RTDMAC2_1_DEI3, 0x1360),
442 INTCS_VECT(RTDMAC2_2_DEI4, 0x1380), INTCS_VECT(RTDMAC2_2_DEI5, 0x13a0),
443 INTCS_VECT(RTDMAC2_2_DADERR, 0x13c0),
444 INTCS_VECT(ISP, 0x1720),
445 INTCS_VECT(LCDC1, 0x1780),
446 INTCS_VECT(CSIRX, 0x17a0),
447 INTCS_VECT(DSITX_DSITX0, 0x17c0),
448 INTCS_VECT(DSITX_DSITX1, 0x17e0),
449 INTCS_VECT(TMU1_TUNI0, 0x1900), INTCS_VECT(TMU1_TUNI1, 0x1920),
450 INTCS_VECT(TMU1_TUNI2, 0x1940),
451 INTCS_VECT(CMT4, 0x1980),
452 INTCS_VECT(DSITX1_DSITX1_0, 0x19a0),
453 INTCS_VECT(DSITX1_DSITX1_1, 0x19c0),
454 INTCS_VECT(CPORTS2R, 0x1a20),
455 INTCS_VECT(JPU6E, 0x1a80),
456
457 INTC_VECT(INTCS, 0xf80),
458};
459
460static struct intc_group intcs_groups[] __initdata = {
461 INTC_GROUP(RTDMAC_1, RTDMAC_1_DEI0, RTDMAC_1_DEI1,
462 RTDMAC_1_DEI2, RTDMAC_1_DEI3),
463 INTC_GROUP(RTDMAC_2, RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR),
464 INTC_GROUP(VEU, VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3),
465 INTC_GROUP(BEU, BEU_BEU0, BEU_BEU1, BEU_BEU2),
466 INTC_GROUP(IIC0, IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0),
467 INTC_GROUP(IPMMU, IPMMU_IPMMUR, IPMMU_IPMMUR2),
468 INTC_GROUP(IIC2, IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2),
469 INTC_GROUP(RTDMAC2_1, RTDMAC2_1_DEI0, RTDMAC2_1_DEI1,
470 RTDMAC2_1_DEI2, RTDMAC2_1_DEI3),
471 INTC_GROUP(RTDMAC2_2, RTDMAC2_2_DEI4,
472 RTDMAC2_2_DEI5, RTDMAC2_2_DADERR),
473 INTC_GROUP(TMU1, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0),
474 INTC_GROUP(DSITX, DSITX_DSITX0, DSITX_DSITX1),
475};
476
477static struct intc_mask_reg intcs_mask_registers[] = {
478 { 0xffd20184, 0xffd201c4, 8, /* IMR1SA / IMCR1SA */
479 { BEU_BEU2, BEU_BEU1, BEU_BEU0, CEU,
480 VEU_VEU3, VEU_VEU2, VEU_VEU1, VEU_VEU0 } },
481 { 0xffd20188, 0xffd201c8, 8, /* IMR2SA / IMCR2SA */
482 { 0, 0, 0, VPU,
483 0, 0, 0, 0 } },
484 { 0xffd2018c, 0xffd201cc, 8, /* IMR3SA / IMCR3SA */
485 { 0, 0, 0, _2DDMAC,
486 0, 0, 0, ICB } },
487 { 0xffd20190, 0xffd201d0, 8, /* IMR4SA / IMCR4SA */
488 { 0, 0, 0, CTI,
489 JPU_JPEG, 0, LCRC, LCDC } },
490 { 0xffd20194, 0xffd201d4, 8, /* IMR5SA / IMCR5SA */
491 { 0, RTDMAC_2_DADERR, RTDMAC_2_DEI5, RTDMAC_2_DEI4,
492 RTDMAC_1_DEI3, RTDMAC_1_DEI2, RTDMAC_1_DEI1, RTDMAC_1_DEI0 } },
493 { 0xffd20198, 0xffd201d8, 8, /* IMR6SA / IMCR6SA */
494 { 0, 0, MSIOF, 0,
495 _3DG_SGX530, 0, 0, 0 } },
496 { 0xffd2019c, 0xffd201dc, 8, /* IMR7SA / IMCR7SA */
497 { 0, TMU_TUNI2, TMU_TUNI1, TMU_TUNI0,
498 0, 0, 0, 0 } },
499 { 0xffd201a4, 0xffd201e4, 8, /* IMR9SA / IMCR9SA */
500 { 0, 0, 0, CMT0,
501 IIC2_DTEI2, IIC2_WAITI2, IIC2_TACKI2, IIC2_ALI2 } },
502 { 0xffd201a8, 0xffd201e8, 8, /* IMR10SA / IMCR10SA */
503 { 0, 0, IPMMU_IPMMUR2, IPMMU_IPMMUR,
504 0, 0, 0, 0 } },
505 { 0xffd201ac, 0xffd201ec, 8, /* IMR11SA / IMCR11SA */
506 { IIC0_DTEI0, IIC0_WAITI0, IIC0_TACKI0, IIC0_ALI0,
507 0, TSIF1, LMB, TSIF0 } },
508 { 0xffd50180, 0xffd501c0, 8, /* IMR0SA3 / IMCR0SA3 */
509 { 0, RTDMAC2_2_DADERR, RTDMAC2_2_DEI5, RTDMAC2_2_DEI4,
510 RTDMAC2_1_DEI3, RTDMAC2_1_DEI2, RTDMAC2_1_DEI1, RTDMAC2_1_DEI0 } },
511 { 0xffd50190, 0xffd501d0, 8, /* IMR4SA3 / IMCR4SA3 */
512 { 0, ISP, 0, 0,
513 LCDC1, CSIRX, DSITX_DSITX0, DSITX_DSITX1 } },
514 { 0xffd50198, 0xffd501d8, 8, /* IMR6SA3 / IMCR6SA3 */
515 { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
516 CMT4, DSITX1_DSITX1_0, DSITX1_DSITX1_1, 0 } },
517 { 0xffd5019c, 0xffd501dc, 8, /* IMR7SA3 / IMCR7SA3 */
518 { 0, CPORTS2R, 0, 0,
519 JPU6E, 0, 0, 0 } },
520 { 0xffd20104, 0, 16, /* INTAMASK */
521 { 0, 0, 0, 0, 0, 0, 0, 0,
522 0, 0, 0, 0, 0, 0, 0, INTCS } },
523};
524
525/* Priority is needed for INTCA to receive the INTCS interrupt */
526static struct intc_prio_reg intcs_prio_registers[] = {
527 { 0xffd20000, 0, 16, 4, /* IPRAS */ { CTI, 0, _2DDMAC, ICB } },
528 { 0xffd20004, 0, 16, 4, /* IPRBS */ { JPU_JPEG, LCDC, 0, LCRC } },
529 { 0xffd20010, 0, 16, 4, /* IPRES */ { RTDMAC_1, CEU, 0, VPU } },
530 { 0xffd20014, 0, 16, 4, /* IPRFS */ { 0, RTDMAC_2, 0, CMT0 } },
531 { 0xffd20018, 0, 16, 4, /* IPRGS */ { TMU_TUNI0, TMU_TUNI1,
532 TMU_TUNI2, TSIF1 } },
533 { 0xffd2001c, 0, 16, 4, /* IPRHS */ { 0, 0, VEU, BEU } },
534 { 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, MSIOF, TSIF0, IIC0 } },
535 { 0xffd20024, 0, 16, 4, /* IPRJS */ { 0, _3DG_SGX530, 0, 0 } },
536 { 0xffd20028, 0, 16, 4, /* IPRKS */ { 0, 0, LMB, 0 } },
537 { 0xffd2002c, 0, 16, 4, /* IPRLS */ { IPMMU, 0, 0, 0 } },
538 { 0xffd20030, 0, 16, 4, /* IPRMS */ { IIC2, 0, 0, 0 } },
539 { 0xffd50000, 0, 16, 4, /* IPRAS3 */ { RTDMAC2_1, 0, 0, 0 } },
540 { 0xffd50004, 0, 16, 4, /* IPRBS3 */ { RTDMAC2_2, 0, 0, 0 } },
541 { 0xffd50020, 0, 16, 4, /* IPRIS3 */ { 0, ISP, 0, 0 } },
542 { 0xffd50024, 0, 16, 4, /* IPRJS3 */ { LCDC1, CSIRX, DSITX, 0 } },
543 { 0xffd50030, 0, 16, 4, /* IPRMS3 */ { TMU1, 0, 0, 0 } },
544 { 0xffd50034, 0, 16, 4, /* IPRNS3 */ { CMT4, DSITX1_DSITX1_0,
545 DSITX1_DSITX1_1, 0 } },
546 { 0xffd50038, 0, 16, 4, /* IPROS3 */ { 0, CPORTS2R, 0, 0 } },
547 { 0xffd5003c, 0, 16, 4, /* IPRPS3 */ { JPU6E, 0, 0, 0 } },
548};
549
550static struct resource intcs_resources[] __initdata = {
551 [0] = {
552 .start = 0xffd20000,
553 .end = 0xffd201ff,
554 .flags = IORESOURCE_MEM,
555 },
556 [1] = {
557 .start = 0xffd50000,
558 .end = 0xffd501ff,
559 .flags = IORESOURCE_MEM,
560 }
561};
562
563static struct intc_desc intcs_desc __initdata = {
564 .name = "sh7372-intcs",
565 .resource = intcs_resources,
566 .num_resources = ARRAY_SIZE(intcs_resources),
567 .hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
568 intcs_prio_registers, NULL, NULL),
569};
570
571static void intcs_demux(unsigned int irq, struct irq_desc *desc)
572{
573 void __iomem *reg = (void *)get_irq_data(irq);
574 unsigned int evtcodeas = ioread32(reg);
575
576 generic_handle_irq(intcs_evt2irq(evtcodeas));
577}
578
366void __init sh7372_init_irq(void) 579void __init sh7372_init_irq(void)
367{ 580{
581 void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
582
368 register_intc_controller(&intca_desc); 583 register_intc_controller(&intca_desc);
584 register_intc_controller(&intcs_desc);
585
586 /* demux using INTEVTSA */
587 set_irq_data(evt2irq(0xf80), (void *)intevtsa);
588 set_irq_chained_handler(evt2irq(0xf80), intcs_demux);
369} 589}
diff --git a/arch/arm/mach-shmobile/intc-sh7377.c b/arch/arm/mach-shmobile/intc-sh7377.c
index 5c781e2d189..2cdeb8ccd82 100644
--- a/arch/arm/mach-shmobile/intc-sh7377.c
+++ b/arch/arm/mach-shmobile/intc-sh7377.c
@@ -90,7 +90,7 @@ enum {
90 ICUSB, ICUDMC 90 ICUSB, ICUDMC
91}; 91};
92 92
93static struct intc_vect intca_vectors[] = { 93static struct intc_vect intca_vectors[] __initdata = {
94 INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220), 94 INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
95 INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260), 95 INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
96 INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0), 96 INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
@@ -202,7 +202,7 @@ static struct intc_group intca_groups[] __initdata = {
202 INTC_GROUP(ICUDMC, ICUDMC_ICUDMC1, ICUDMC_ICUDMC2), 202 INTC_GROUP(ICUDMC, ICUDMC_ICUDMC1, ICUDMC_ICUDMC2),
203}; 203};
204 204
205static struct intc_mask_reg intca_mask_registers[] = { 205static struct intc_mask_reg intca_mask_registers[] __initdata = {
206 { 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */ 206 { 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
207 { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } }, 207 { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
208 { 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */ 208 { 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
@@ -272,7 +272,7 @@ static struct intc_mask_reg intca_mask_registers[] = {
272 SCIFA6, 0, 0, 0 } }, 272 SCIFA6, 0, 0, 0 } },
273}; 273};
274 274
275static struct intc_prio_reg intca_prio_registers[] = { 275static struct intc_prio_reg intca_prio_registers[] __initdata = {
276 { 0xe6900010, 0, 32, 4, /* INTPRI00A */ 276 { 0xe6900010, 0, 32, 4, /* INTPRI00A */
277 { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } }, 277 { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
278 { 0xe6900014, 0, 32, 4, /* INTPRI10A */ 278 { 0xe6900014, 0, 32, 4, /* INTPRI10A */
@@ -346,7 +346,301 @@ static struct intc_desc intca_desc __initdata = {
346 intca_sense_registers, intca_ack_registers), 346 intca_sense_registers, intca_ack_registers),
347}; 347};
348 348
349/* this macro ignore entry which is also in INTCA */
350#define __IGNORE(a...)
351#define __IGNORE0(a...) 0
352
353enum {
354 UNUSED_INTCS = 0,
355
356 INTCS,
357
358 /* interrupt sources INTCS */
359 VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3,
360 RTDMAC1_1_DEI0, RTDMAC1_1_DEI1, RTDMAC1_1_DEI2, RTDMAC1_1_DEI3,
361 CEU,
362 BEU_BEU0, BEU_BEU1, BEU_BEU2,
363 __IGNORE(MFI)
364 __IGNORE(BBIF2)
365 VPU,
366 TSIF1,
367 __IGNORE(SGX540)
368 _2DDMAC,
369 IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2,
370 IPMMU_IPMMUR, IPMMU_IPMMUR2,
371 RTDMAC1_2_DEI4, RTDMAC1_2_DEI5, RTDMAC1_2_DADERR,
372 __IGNORE(KEYSC)
373 __IGNORE(TTI20)
374 __IGNORE(MSIOF)
375 IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0,
376 TMU_TUNI0, TMU_TUNI1, TMU_TUNI2,
377 CMT0,
378 TSIF0,
379 __IGNORE(CMT2)
380 LMB,
381 __IGNORE(MSUG)
382 __IGNORE(MSU_MSU, MSU_MSU2)
383 __IGNORE(CTI)
384 MVI3,
385 __IGNORE(RWDT0)
386 __IGNORE(RWDT1)
387 ICB,
388 PEP,
389 ASA,
390 __IGNORE(_2DG)
391 HQE,
392 JPU,
393 LCDC0,
394 __IGNORE(LCRC)
395 RTDMAC2_1_DEI0, RTDMAC2_1_DEI1, RTDMAC2_1_DEI2, RTDMAC2_1_DEI3,
396 RTDMAC2_2_DEI4, RTDMAC2_2_DEI5, RTDMAC2_2_DADERR,
397 FRC,
398 LCDC1,
399 CSIRX,
400 DSITX_DSITX0, DSITX_DSITX1,
401 __IGNORE(SPU2_SPU0, SPU2_SPU1)
402 __IGNORE(FSI)
403 __IGNORE(FMSI)
404 __IGNORE(SCUV)
405 TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12,
406 TSIF2,
407 CMT4,
408 __IGNORE(MFIS2)
409 CPORTS2R,
410
411 /* interrupt groups INTCS */
412 RTDMAC1_1, RTDMAC1_2, VEU, BEU, IIC0, __IGNORE(MSU) IPMMU,
413 IIC2, RTDMAC2_1, RTDMAC2_2, DSITX, __IGNORE(SPU2) TMU1,
414};
415
416#define INTCS_INTVECT 0x0F80
417static struct intc_vect intcs_vectors[] __initdata = {
418 INTCS_VECT(VEU_VEU0, 0x0700), INTCS_VECT(VEU_VEU1, 0x0720),
419 INTCS_VECT(VEU_VEU2, 0x0740), INTCS_VECT(VEU_VEU3, 0x0760),
420 INTCS_VECT(RTDMAC1_1_DEI0, 0x0800), INTCS_VECT(RTDMAC1_1_DEI1, 0x0820),
421 INTCS_VECT(RTDMAC1_1_DEI2, 0x0840), INTCS_VECT(RTDMAC1_1_DEI3, 0x0860),
422 INTCS_VECT(CEU, 0x0880),
423 INTCS_VECT(BEU_BEU0, 0x08A0),
424 INTCS_VECT(BEU_BEU1, 0x08C0),
425 INTCS_VECT(BEU_BEU2, 0x08E0),
426 __IGNORE(INTCS_VECT(MFI, 0x0900))
427 __IGNORE(INTCS_VECT(BBIF2, 0x0960))
428 INTCS_VECT(VPU, 0x0980),
429 INTCS_VECT(TSIF1, 0x09A0),
430 __IGNORE(INTCS_VECT(SGX540, 0x09E0))
431 INTCS_VECT(_2DDMAC, 0x0A00),
432 INTCS_VECT(IIC2_ALI2, 0x0A80), INTCS_VECT(IIC2_TACKI2, 0x0AA0),
433 INTCS_VECT(IIC2_WAITI2, 0x0AC0), INTCS_VECT(IIC2_DTEI2, 0x0AE0),
434 INTCS_VECT(IPMMU_IPMMUR, 0x0B00), INTCS_VECT(IPMMU_IPMMUR2, 0x0B20),
435 INTCS_VECT(RTDMAC1_2_DEI4, 0x0B80),
436 INTCS_VECT(RTDMAC1_2_DEI5, 0x0BA0),
437 INTCS_VECT(RTDMAC1_2_DADERR, 0x0BC0),
438 __IGNORE(INTCS_VECT(KEYSC 0x0BE0))
439 __IGNORE(INTCS_VECT(TTI20, 0x0C80))
440 __IGNORE(INTCS_VECT(MSIOF, 0x0D20))
441 INTCS_VECT(IIC0_ALI0, 0x0E00), INTCS_VECT(IIC0_TACKI0, 0x0E20),
442 INTCS_VECT(IIC0_WAITI0, 0x0E40), INTCS_VECT(IIC0_DTEI0, 0x0E60),
443 INTCS_VECT(TMU_TUNI0, 0x0E80),
444 INTCS_VECT(TMU_TUNI1, 0x0EA0),
445 INTCS_VECT(TMU_TUNI2, 0x0EC0),
446 INTCS_VECT(CMT0, 0x0F00),
447 INTCS_VECT(TSIF0, 0x0F20),
448 __IGNORE(INTCS_VECT(CMT2, 0x0F40))
449 INTCS_VECT(LMB, 0x0F60),
450 __IGNORE(INTCS_VECT(MSUG, 0x0F80))
451 __IGNORE(INTCS_VECT(MSU_MSU, 0x0FA0))
452 __IGNORE(INTCS_VECT(MSU_MSU2, 0x0FC0))
453 __IGNORE(INTCS_VECT(CTI, 0x0400))
454 INTCS_VECT(MVI3, 0x0420),
455 __IGNORE(INTCS_VECT(RWDT0, 0x0440))
456 __IGNORE(INTCS_VECT(RWDT1, 0x0460))
457 INTCS_VECT(ICB, 0x0480),
458 INTCS_VECT(PEP, 0x04A0),
459 INTCS_VECT(ASA, 0x04C0),
460 __IGNORE(INTCS_VECT(_2DG, 0x04E0))
461 INTCS_VECT(HQE, 0x0540),
462 INTCS_VECT(JPU, 0x0560),
463 INTCS_VECT(LCDC0, 0x0580),
464 __IGNORE(INTCS_VECT(LCRC, 0x05A0))
465 INTCS_VECT(RTDMAC2_1_DEI0, 0x1300), INTCS_VECT(RTDMAC2_1_DEI1, 0x1320),
466 INTCS_VECT(RTDMAC2_1_DEI2, 0x1340), INTCS_VECT(RTDMAC2_1_DEI3, 0x1360),
467 INTCS_VECT(RTDMAC2_2_DEI4, 0x1380), INTCS_VECT(RTDMAC2_2_DEI5, 0x13A0),
468 INTCS_VECT(RTDMAC2_2_DADERR, 0x13C0),
469 INTCS_VECT(FRC, 0x1700),
470 INTCS_VECT(LCDC1, 0x1780),
471 INTCS_VECT(CSIRX, 0x17A0),
472 INTCS_VECT(DSITX_DSITX0, 0x17C0), INTCS_VECT(DSITX_DSITX1, 0x17E0),
473 __IGNORE(INTCS_VECT(SPU2_SPU0, 0x1800))
474 __IGNORE(INTCS_VECT(SPU2_SPU1, 0x1820))
475 __IGNORE(INTCS_VECT(FSI, 0x1840))
476 __IGNORE(INTCS_VECT(FMSI, 0x1860))
477 __IGNORE(INTCS_VECT(SCUV, 0x1880))
478 INTCS_VECT(TMU1_TUNI10, 0x1900), INTCS_VECT(TMU1_TUNI11, 0x1920),
479 INTCS_VECT(TMU1_TUNI12, 0x1940),
480 INTCS_VECT(TSIF2, 0x1960),
481 INTCS_VECT(CMT4, 0x1980),
482 __IGNORE(INTCS_VECT(MFIS2, 0x1A00))
483 INTCS_VECT(CPORTS2R, 0x1A20),
484
485 INTC_VECT(INTCS, INTCS_INTVECT),
486};
487
488static struct intc_group intcs_groups[] __initdata = {
489 INTC_GROUP(RTDMAC1_1,
490 RTDMAC1_1_DEI0, RTDMAC1_1_DEI1,
491 RTDMAC1_1_DEI2, RTDMAC1_1_DEI3),
492 INTC_GROUP(RTDMAC1_2,
493 RTDMAC1_2_DEI4, RTDMAC1_2_DEI5, RTDMAC1_2_DADERR),
494 INTC_GROUP(VEU, VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3),
495 INTC_GROUP(BEU, BEU_BEU0, BEU_BEU1, BEU_BEU2),
496 INTC_GROUP(IIC0, IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0),
497 __IGNORE(INTC_GROUP(MSU, MSU_MSU, MSU_MSU2))
498 INTC_GROUP(IPMMU, IPMMU_IPMMUR, IPMMU_IPMMUR2),
499 INTC_GROUP(IIC2, IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2),
500 INTC_GROUP(RTDMAC2_1,
501 RTDMAC2_1_DEI0, RTDMAC2_1_DEI1,
502 RTDMAC2_1_DEI2, RTDMAC2_1_DEI3),
503 INTC_GROUP(RTDMAC2_2, RTDMAC2_2_DEI4, RTDMAC2_2_DEI5, RTDMAC2_2_DADERR),
504 INTC_GROUP(DSITX, DSITX_DSITX0, DSITX_DSITX1),
505 __IGNORE(INTC_GROUP(SPU2, SPU2_SPU0, SPU2_SPU1))
506 INTC_GROUP(TMU1, TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12),
507};
508
509static struct intc_mask_reg intcs_mask_registers[] __initdata = {
510 { 0xE6940184, 0xE69401C4, 8, /* IMR1AS / IMCR1AS */
511 { BEU_BEU2, BEU_BEU1, BEU_BEU0, CEU,
512 VEU_VEU3, VEU_VEU2, VEU_VEU1, VEU_VEU0 } },
513 { 0xE6940188, 0xE69401C8, 8, /* IMR2AS / IMCR2AS */
514 { 0, 0, 0, VPU,
515 __IGNORE0(BBIF2), 0, 0, __IGNORE0(MFI) } },
516 { 0xE694018C, 0xE69401CC, 8, /* IMR3AS / IMCR3AS */
517 { 0, 0, 0, _2DDMAC,
518 __IGNORE0(_2DG), ASA, PEP, ICB } },
519 { 0xE6940190, 0xE69401D0, 8, /* IMR4AS / IMCR4AS */
520 { 0, 0, MVI3, __IGNORE0(CTI),
521 JPU, HQE, __IGNORE0(LCRC), LCDC0 } },
522 { 0xE6940194, 0xE69401D4, 8, /* IMR5AS / IMCR5AS */
523 { __IGNORE0(KEYSC), RTDMAC1_2_DADERR, RTDMAC1_2_DEI5, RTDMAC1_2_DEI4,
524 RTDMAC1_1_DEI3, RTDMAC1_1_DEI2, RTDMAC1_1_DEI1, RTDMAC1_1_DEI0 } },
525 __IGNORE({ 0xE6940198, 0xE69401D8, 8, /* IMR6AS / IMCR6AS */
526 { 0, 0, MSIOF, 0,
527 SGX540, 0, TTI20, 0 } })
528 { 0xE694019C, 0xE69401DC, 8, /* IMR7AS / IMCR7AS */
529 { 0, TMU_TUNI2, TMU_TUNI1, TMU_TUNI0,
530 0, 0, 0, 0 } },
531 __IGNORE({ 0xE69401A0, 0xE69401E0, 8, /* IMR8AS / IMCR8AS */
532 { 0, 0, 0, 0,
533 0, MSU_MSU, MSU_MSU2, MSUG } })
534 { 0xE69401A4, 0xE69401E4, 8, /* IMR9AS / IMCR9AS */
535 { __IGNORE0(RWDT1), __IGNORE0(RWDT0), __IGNORE0(CMT2), CMT0,
536 IIC2_DTEI2, IIC2_WAITI2, IIC2_TACKI2, IIC2_ALI2 } },
537 { 0xE69401A8, 0xE69401E8, 8, /* IMR10AS / IMCR10AS */
538 { 0, 0, IPMMU_IPMMUR, IPMMU_IPMMUR2,
539 0, 0, 0, 0 } },
540 { 0xE69401AC, 0xE69401EC, 8, /* IMR11AS / IMCR11AS */
541 { IIC0_DTEI0, IIC0_WAITI0, IIC0_TACKI0, IIC0_ALI0,
542 0, TSIF1, LMB, TSIF0 } },
543 { 0xE6950180, 0xE69501C0, 8, /* IMR0AS3 / IMCR0AS3 */
544 { RTDMAC2_1_DEI0, RTDMAC2_1_DEI1, RTDMAC2_1_DEI2, RTDMAC2_1_DEI3,
545 RTDMAC2_2_DEI4, RTDMAC2_2_DEI5, RTDMAC2_2_DADERR, 0 } },
546 { 0xE6950190, 0xE69501D0, 8, /* IMR4AS3 / IMCR4AS3 */
547 { FRC, 0, 0, 0,
548 LCDC1, CSIRX, DSITX_DSITX0, DSITX_DSITX1 } },
549 __IGNORE({ 0xE6950194, 0xE69501D4, 8, /* IMR5AS3 / IMCR5AS3 */
550 {SPU2_SPU0, SPU2_SPU1, FSI, FMSI,
551 SCUV, 0, 0, 0 } })
552 { 0xE6950198, 0xE69501D8, 8, /* IMR6AS3 / IMCR6AS3 */
553 { TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12, TSIF2,
554 CMT4, 0, 0, 0 } },
555 { 0xE695019C, 0xE69501DC, 8, /* IMR7AS3 / IMCR7AS3 */
556 { __IGNORE0(MFIS2), CPORTS2R, 0, 0,
557 0, 0, 0, 0 } },
558 { 0xFFD20104, 0, 16, /* INTAMASK */
559 { 0, 0, 0, 0, 0, 0, 0, 0,
560 0, 0, 0, 0, 0, 0, 0, INTCS } }
561};
562
563static struct intc_prio_reg intcs_prio_registers[] __initdata = {
564 /* IPRAS */
565 { 0xFFD20000, 0, 16, 4, { __IGNORE0(CTI), MVI3, _2DDMAC, ICB } },
566 /* IPRBS */
567 { 0xFFD20004, 0, 16, 4, { JPU, LCDC0, 0, __IGNORE0(LCRC) } },
568 /* IPRCS */
569 __IGNORE({ 0xFFD20008, 0, 16, 4, { BBIF2, 0, 0, 0 } })
570 /* IPRES */
571 { 0xFFD20010, 0, 16, 4, { RTDMAC1_1, CEU, __IGNORE0(MFI), VPU } },
572 /* IPRFS */
573 { 0xFFD20014, 0, 16, 4,
574 { __IGNORE0(KEYSC), RTDMAC1_2, __IGNORE0(CMT2), CMT0 } },
575 /* IPRGS */
576 { 0xFFD20018, 0, 16, 4, { TMU_TUNI0, TMU_TUNI1, TMU_TUNI2, TSIF1 } },
577 /* IPRHS */
578 { 0xFFD2001C, 0, 16, 4, { __IGNORE0(TTI20), 0, VEU, BEU } },
579 /* IPRIS */
580 { 0xFFD20020, 0, 16, 4, { 0, __IGNORE0(MSIOF), TSIF0, IIC0 } },
581 /* IPRJS */
582 __IGNORE({ 0xFFD20024, 0, 16, 4, { 0, SGX540, MSUG, MSU } })
583 /* IPRKS */
584 { 0xFFD20028, 0, 16, 4, { __IGNORE0(_2DG), ASA, LMB, PEP } },
585 /* IPRLS */
586 { 0xFFD2002C, 0, 16, 4, { IPMMU, 0, 0, HQE } },
587 /* IPRMS */
588 { 0xFFD20030, 0, 16, 4,
589 { IIC2, 0, __IGNORE0(RWDT1), __IGNORE0(RWDT0) } },
590 /* IPRAS3 */
591 { 0xFFD50000, 0, 16, 4, { RTDMAC2_1, 0, 0, 0 } },
592 /* IPRBS3 */
593 { 0xFFD50004, 0, 16, 4, { RTDMAC2_2, 0, 0, 0 } },
594 /* IPRIS3 */
595 { 0xFFD50020, 0, 16, 4, { FRC, 0, 0, 0 } },
596 /* IPRJS3 */
597 { 0xFFD50024, 0, 16, 4, { LCDC1, CSIRX, DSITX, 0 } },
598 /* IPRKS3 */
599 __IGNORE({ 0xFFD50028, 0, 16, 4, { SPU2, 0, FSI, FMSI } })
600 /* IPRLS3 */
601 __IGNORE({ 0xFFD5002C, 0, 16, 4, { SCUV, 0, 0, 0 } })
602 /* IPRMS3 */
603 { 0xFFD50030, 0, 16, 4, { TMU1, 0, 0, TSIF2 } },
604 /* IPRNS3 */
605 { 0xFFD50034, 0, 16, 4, { CMT4, 0, 0, 0 } },
606 /* IPROS3 */
607 { 0xFFD50038, 0, 16, 4, { __IGNORE0(MFIS2), CPORTS2R, 0, 0 } },
608};
609
610static struct resource intcs_resources[] __initdata = {
611 [0] = {
612 .start = 0xffd20000,
613 .end = 0xffd500ff,
614 .flags = IORESOURCE_MEM,
615 }
616};
617
618static struct intc_desc intcs_desc __initdata = {
619 .name = "sh7377-intcs",
620 .resource = intcs_resources,
621 .num_resources = ARRAY_SIZE(intcs_resources),
622 .hw = INTC_HW_DESC(intcs_vectors, intcs_groups,
623 intcs_mask_registers, intcs_prio_registers,
624 NULL, NULL),
625};
626
627static void intcs_demux(unsigned int irq, struct irq_desc *desc)
628{
629 void __iomem *reg = (void *)get_irq_data(irq);
630 unsigned int evtcodeas = ioread32(reg);
631
632 generic_handle_irq(intcs_evt2irq(evtcodeas));
633}
634
635#define INTEVTSA 0xFFD20100
349void __init sh7377_init_irq(void) 636void __init sh7377_init_irq(void)
350{ 637{
638 void __iomem *intevtsa = ioremap_nocache(INTEVTSA, PAGE_SIZE);
639
351 register_intc_controller(&intca_desc); 640 register_intc_controller(&intca_desc);
641 register_intc_controller(&intcs_desc);
642
643 /* demux using INTEVTSA */
644 set_irq_data(evt2irq(INTCS_INTVECT), (void *)intevtsa);
645 set_irq_chained_handler(evt2irq(INTCS_INTVECT), intcs_demux);
352} 646}
diff --git a/arch/arm/mach-shmobile/pfc-sh7372.c b/arch/arm/mach-shmobile/pfc-sh7372.c
index 9557d0964d7..ec420353f8e 100644
--- a/arch/arm/mach-shmobile/pfc-sh7372.c
+++ b/arch/arm/mach-shmobile/pfc-sh7372.c
@@ -1160,6 +1160,9 @@ static struct pinmux_gpio pinmux_gpios[] = {
1160 GPIO_FN(LCDD18), GPIO_FN(LCDD19), GPIO_FN(LCDD20), 1160 GPIO_FN(LCDD18), GPIO_FN(LCDD19), GPIO_FN(LCDD20),
1161 GPIO_FN(LCDD21), GPIO_FN(LCDD22), GPIO_FN(LCDD23), 1161 GPIO_FN(LCDD21), GPIO_FN(LCDD22), GPIO_FN(LCDD23),
1162 1162
1163 GPIO_FN(LCDC0_SELECT),
1164 GPIO_FN(LCDC1_SELECT),
1165
1163 /* IRDA */ 1166 /* IRDA */
1164 GPIO_FN(IRDA_OUT), GPIO_FN(IRDA_IN), GPIO_FN(IRDA_FIRSEL), 1167 GPIO_FN(IRDA_OUT), GPIO_FN(IRDA_IN), GPIO_FN(IRDA_FIRSEL),
1165 GPIO_FN(IROUT_139), GPIO_FN(IROUT_140), 1168 GPIO_FN(IROUT_139), GPIO_FN(IROUT_140),
diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c
index eca90716140..3148c11a550 100644
--- a/arch/arm/mach-shmobile/setup-sh7367.c
+++ b/arch/arm/mach-shmobile/setup-sh7367.c
@@ -31,11 +31,13 @@
31#include <asm/mach-types.h> 31#include <asm/mach-types.h>
32#include <asm/mach/arch.h> 32#include <asm/mach/arch.h>
33 33
34/* SCIFA0 */
34static struct plat_sci_port scif0_platform_data = { 35static struct plat_sci_port scif0_platform_data = {
35 .mapbase = 0xe6c40000, 36 .mapbase = 0xe6c40000,
36 .flags = UPF_BOOT_AUTOCONF, 37 .flags = UPF_BOOT_AUTOCONF,
37 .type = PORT_SCIF, 38 .type = PORT_SCIF,
38 .irqs = { 80, 80, 80, 80 }, 39 .irqs = { evt2irq(0xc00), evt2irq(0xc00),
40 evt2irq(0xc00), evt2irq(0xc00) },
39}; 41};
40 42
41static struct platform_device scif0_device = { 43static struct platform_device scif0_device = {
@@ -46,11 +48,13 @@ static struct platform_device scif0_device = {
46 }, 48 },
47}; 49};
48 50
51/* SCIFA1 */
49static struct plat_sci_port scif1_platform_data = { 52static struct plat_sci_port scif1_platform_data = {
50 .mapbase = 0xe6c50000, 53 .mapbase = 0xe6c50000,
51 .flags = UPF_BOOT_AUTOCONF, 54 .flags = UPF_BOOT_AUTOCONF,
52 .type = PORT_SCIF, 55 .type = PORT_SCIF,
53 .irqs = { 81, 81, 81, 81 }, 56 .irqs = { evt2irq(0xc20), evt2irq(0xc20),
57 evt2irq(0xc20), evt2irq(0xc20) },
54}; 58};
55 59
56static struct platform_device scif1_device = { 60static struct platform_device scif1_device = {
@@ -61,11 +65,13 @@ static struct platform_device scif1_device = {
61 }, 65 },
62}; 66};
63 67
68/* SCIFA2 */
64static struct plat_sci_port scif2_platform_data = { 69static struct plat_sci_port scif2_platform_data = {
65 .mapbase = 0xe6c60000, 70 .mapbase = 0xe6c60000,
66 .flags = UPF_BOOT_AUTOCONF, 71 .flags = UPF_BOOT_AUTOCONF,
67 .type = PORT_SCIF, 72 .type = PORT_SCIF,
68 .irqs = { 82, 82, 82, 82 }, 73 .irqs = { evt2irq(0xc40), evt2irq(0xc40),
74 evt2irq(0xc40), evt2irq(0xc40) },
69}; 75};
70 76
71static struct platform_device scif2_device = { 77static struct platform_device scif2_device = {
@@ -76,11 +82,13 @@ static struct platform_device scif2_device = {
76 }, 82 },
77}; 83};
78 84
85/* SCIFA3 */
79static struct plat_sci_port scif3_platform_data = { 86static struct plat_sci_port scif3_platform_data = {
80 .mapbase = 0xe6c70000, 87 .mapbase = 0xe6c70000,
81 .flags = UPF_BOOT_AUTOCONF, 88 .flags = UPF_BOOT_AUTOCONF,
82 .type = PORT_SCIF, 89 .type = PORT_SCIF,
83 .irqs = { 83, 83, 83, 83 }, 90 .irqs = { evt2irq(0xc60), evt2irq(0xc60),
91 evt2irq(0xc60), evt2irq(0xc60) },
84}; 92};
85 93
86static struct platform_device scif3_device = { 94static struct platform_device scif3_device = {
@@ -91,11 +99,13 @@ static struct platform_device scif3_device = {
91 }, 99 },
92}; 100};
93 101
102/* SCIFA4 */
94static struct plat_sci_port scif4_platform_data = { 103static struct plat_sci_port scif4_platform_data = {
95 .mapbase = 0xe6c80000, 104 .mapbase = 0xe6c80000,
96 .flags = UPF_BOOT_AUTOCONF, 105 .flags = UPF_BOOT_AUTOCONF,
97 .type = PORT_SCIF, 106 .type = PORT_SCIF,
98 .irqs = { 89, 89, 89, 89 }, 107 .irqs = { evt2irq(0xd20), evt2irq(0xd20),
108 evt2irq(0xd20), evt2irq(0xd20) },
99}; 109};
100 110
101static struct platform_device scif4_device = { 111static struct platform_device scif4_device = {
@@ -106,11 +116,13 @@ static struct platform_device scif4_device = {
106 }, 116 },
107}; 117};
108 118
119/* SCIFA5 */
109static struct plat_sci_port scif5_platform_data = { 120static struct plat_sci_port scif5_platform_data = {
110 .mapbase = 0xe6cb0000, 121 .mapbase = 0xe6cb0000,
111 .flags = UPF_BOOT_AUTOCONF, 122 .flags = UPF_BOOT_AUTOCONF,
112 .type = PORT_SCIF, 123 .type = PORT_SCIF,
113 .irqs = { 90, 90, 90, 90 }, 124 .irqs = { evt2irq(0xd40), evt2irq(0xd40),
125 evt2irq(0xd40), evt2irq(0xd40) },
114}; 126};
115 127
116static struct platform_device scif5_device = { 128static struct platform_device scif5_device = {
@@ -121,11 +133,13 @@ static struct platform_device scif5_device = {
121 }, 133 },
122}; 134};
123 135
136/* SCIFB */
124static struct plat_sci_port scif6_platform_data = { 137static struct plat_sci_port scif6_platform_data = {
125 .mapbase = 0xe6c30000, 138 .mapbase = 0xe6c30000,
126 .flags = UPF_BOOT_AUTOCONF, 139 .flags = UPF_BOOT_AUTOCONF,
127 .type = PORT_SCIF, 140 .type = PORT_SCIF,
128 .irqs = { 91, 91, 91, 91 }, 141 .irqs = { evt2irq(0xd60), evt2irq(0xd60),
142 evt2irq(0xd60), evt2irq(0xd60) },
129}; 143};
130 144
131static struct platform_device scif6_device = { 145static struct platform_device scif6_device = {
@@ -153,7 +167,7 @@ static struct resource cmt10_resources[] = {
153 .flags = IORESOURCE_MEM, 167 .flags = IORESOURCE_MEM,
154 }, 168 },
155 [1] = { 169 [1] = {
156 .start = 72, 170 .start = evt2irq(0xb00), /* CMT1_CMT10 */
157 .flags = IORESOURCE_IRQ, 171 .flags = IORESOURCE_IRQ,
158 }, 172 },
159}; 173};
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 1d1153290f5..e26686c9d0b 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -26,17 +26,21 @@
26#include <linux/input.h> 26#include <linux/input.h>
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/serial_sci.h> 28#include <linux/serial_sci.h>
29#include <linux/sh_dma.h>
29#include <linux/sh_intc.h> 30#include <linux/sh_intc.h>
30#include <linux/sh_timer.h> 31#include <linux/sh_timer.h>
31#include <mach/hardware.h> 32#include <mach/hardware.h>
33#include <mach/sh7372.h>
32#include <asm/mach-types.h> 34#include <asm/mach-types.h>
33#include <asm/mach/arch.h> 35#include <asm/mach/arch.h>
34 36
37/* SCIFA0 */
35static struct plat_sci_port scif0_platform_data = { 38static struct plat_sci_port scif0_platform_data = {
36 .mapbase = 0xe6c40000, 39 .mapbase = 0xe6c40000,
37 .flags = UPF_BOOT_AUTOCONF, 40 .flags = UPF_BOOT_AUTOCONF,
38 .type = PORT_SCIF, 41 .type = PORT_SCIFA,
39 .irqs = { 80, 80, 80, 80 }, 42 .irqs = { evt2irq(0x0c00), evt2irq(0x0c00),
43 evt2irq(0x0c00), evt2irq(0x0c00) },
40}; 44};
41 45
42static struct platform_device scif0_device = { 46static struct platform_device scif0_device = {
@@ -47,11 +51,13 @@ static struct platform_device scif0_device = {
47 }, 51 },
48}; 52};
49 53
54/* SCIFA1 */
50static struct plat_sci_port scif1_platform_data = { 55static struct plat_sci_port scif1_platform_data = {
51 .mapbase = 0xe6c50000, 56 .mapbase = 0xe6c50000,
52 .flags = UPF_BOOT_AUTOCONF, 57 .flags = UPF_BOOT_AUTOCONF,
53 .type = PORT_SCIF, 58 .type = PORT_SCIFA,
54 .irqs = { 81, 81, 81, 81 }, 59 .irqs = { evt2irq(0x0c20), evt2irq(0x0c20),
60 evt2irq(0x0c20), evt2irq(0x0c20) },
55}; 61};
56 62
57static struct platform_device scif1_device = { 63static struct platform_device scif1_device = {
@@ -62,11 +68,13 @@ static struct platform_device scif1_device = {
62 }, 68 },
63}; 69};
64 70
71/* SCIFA2 */
65static struct plat_sci_port scif2_platform_data = { 72static struct plat_sci_port scif2_platform_data = {
66 .mapbase = 0xe6c60000, 73 .mapbase = 0xe6c60000,
67 .flags = UPF_BOOT_AUTOCONF, 74 .flags = UPF_BOOT_AUTOCONF,
68 .type = PORT_SCIF, 75 .type = PORT_SCIFA,
69 .irqs = { 82, 82, 82, 82 }, 76 .irqs = { evt2irq(0x0c40), evt2irq(0x0c40),
77 evt2irq(0x0c40), evt2irq(0x0c40) },
70}; 78};
71 79
72static struct platform_device scif2_device = { 80static struct platform_device scif2_device = {
@@ -77,11 +85,13 @@ static struct platform_device scif2_device = {
77 }, 85 },
78}; 86};
79 87
88/* SCIFA3 */
80static struct plat_sci_port scif3_platform_data = { 89static struct plat_sci_port scif3_platform_data = {
81 .mapbase = 0xe6c70000, 90 .mapbase = 0xe6c70000,
82 .flags = UPF_BOOT_AUTOCONF, 91 .flags = UPF_BOOT_AUTOCONF,
83 .type = PORT_SCIF, 92 .type = PORT_SCIFA,
84 .irqs = { 83, 83, 83, 83 }, 93 .irqs = { evt2irq(0x0c60), evt2irq(0x0c60),
94 evt2irq(0x0c60), evt2irq(0x0c60) },
85}; 95};
86 96
87static struct platform_device scif3_device = { 97static struct platform_device scif3_device = {
@@ -92,11 +102,13 @@ static struct platform_device scif3_device = {
92 }, 102 },
93}; 103};
94 104
105/* SCIFA4 */
95static struct plat_sci_port scif4_platform_data = { 106static struct plat_sci_port scif4_platform_data = {
96 .mapbase = 0xe6c80000, 107 .mapbase = 0xe6c80000,
97 .flags = UPF_BOOT_AUTOCONF, 108 .flags = UPF_BOOT_AUTOCONF,
98 .type = PORT_SCIF, 109 .type = PORT_SCIFA,
99 .irqs = { 89, 89, 89, 89 }, 110 .irqs = { evt2irq(0x0d20), evt2irq(0x0d20),
111 evt2irq(0x0d20), evt2irq(0x0d20) },
100}; 112};
101 113
102static struct platform_device scif4_device = { 114static struct platform_device scif4_device = {
@@ -107,11 +119,13 @@ static struct platform_device scif4_device = {
107 }, 119 },
108}; 120};
109 121
122/* SCIFA5 */
110static struct plat_sci_port scif5_platform_data = { 123static struct plat_sci_port scif5_platform_data = {
111 .mapbase = 0xe6cb0000, 124 .mapbase = 0xe6cb0000,
112 .flags = UPF_BOOT_AUTOCONF, 125 .flags = UPF_BOOT_AUTOCONF,
113 .type = PORT_SCIF, 126 .type = PORT_SCIFA,
114 .irqs = { 90, 90, 90, 90 }, 127 .irqs = { evt2irq(0x0d40), evt2irq(0x0d40),
128 evt2irq(0x0d40), evt2irq(0x0d40) },
115}; 129};
116 130
117static struct platform_device scif5_device = { 131static struct platform_device scif5_device = {
@@ -122,11 +136,13 @@ static struct platform_device scif5_device = {
122 }, 136 },
123}; 137};
124 138
139/* SCIFB */
125static struct plat_sci_port scif6_platform_data = { 140static struct plat_sci_port scif6_platform_data = {
126 .mapbase = 0xe6c30000, 141 .mapbase = 0xe6c30000,
127 .flags = UPF_BOOT_AUTOCONF, 142 .flags = UPF_BOOT_AUTOCONF,
128 .type = PORT_SCIF, 143 .type = PORT_SCIFB,
129 .irqs = { 91, 91, 91, 91 }, 144 .irqs = { evt2irq(0x0d60), evt2irq(0x0d60),
145 evt2irq(0x0d60), evt2irq(0x0d60) },
130}; 146};
131 147
132static struct platform_device scif6_device = { 148static struct platform_device scif6_device = {
@@ -137,11 +153,12 @@ static struct platform_device scif6_device = {
137 }, 153 },
138}; 154};
139 155
156/* CMT */
140static struct sh_timer_config cmt10_platform_data = { 157static struct sh_timer_config cmt10_platform_data = {
141 .name = "CMT10", 158 .name = "CMT10",
142 .channel_offset = 0x10, 159 .channel_offset = 0x10,
143 .timer_bit = 0, 160 .timer_bit = 0,
144 .clk = "r_clk", 161 .clk = "cmt1",
145 .clockevent_rating = 125, 162 .clockevent_rating = 125,
146 .clocksource_rating = 125, 163 .clocksource_rating = 125,
147}; 164};
@@ -154,7 +171,7 @@ static struct resource cmt10_resources[] = {
154 .flags = IORESOURCE_MEM, 171 .flags = IORESOURCE_MEM,
155 }, 172 },
156 [1] = { 173 [1] = {
157 .start = 72, 174 .start = evt2irq(0x0b00), /* CMT1_CMT10 */
158 .flags = IORESOURCE_IRQ, 175 .flags = IORESOURCE_IRQ,
159 }, 176 },
160}; 177};
@@ -169,6 +186,337 @@ static struct platform_device cmt10_device = {
169 .num_resources = ARRAY_SIZE(cmt10_resources), 186 .num_resources = ARRAY_SIZE(cmt10_resources),
170}; 187};
171 188
189/* I2C */
190static struct resource iic0_resources[] = {
191 [0] = {
192 .name = "IIC0",
193 .start = 0xFFF20000,
194 .end = 0xFFF20425 - 1,
195 .flags = IORESOURCE_MEM,
196 },
197 [1] = {
198 .start = intcs_evt2irq(0xe00), /* IIC0_ALI0 */
199 .end = intcs_evt2irq(0xe60), /* IIC0_DTEI0 */
200 .flags = IORESOURCE_IRQ,
201 },
202};
203
204static struct platform_device iic0_device = {
205 .name = "i2c-sh_mobile",
206 .id = 0, /* "i2c0" clock */
207 .num_resources = ARRAY_SIZE(iic0_resources),
208 .resource = iic0_resources,
209};
210
211static struct resource iic1_resources[] = {
212 [0] = {
213 .name = "IIC1",
214 .start = 0xE6C20000,
215 .end = 0xE6C20425 - 1,
216 .flags = IORESOURCE_MEM,
217 },
218 [1] = {
219 .start = evt2irq(0x780), /* IIC1_ALI1 */
220 .end = evt2irq(0x7e0), /* IIC1_DTEI1 */
221 .flags = IORESOURCE_IRQ,
222 },
223};
224
225static struct platform_device iic1_device = {
226 .name = "i2c-sh_mobile",
227 .id = 1, /* "i2c1" clock */
228 .num_resources = ARRAY_SIZE(iic1_resources),
229 .resource = iic1_resources,
230};
231
232/* DMA */
233/* Transmit sizes and respective CHCR register values */
234enum {
235 XMIT_SZ_8BIT = 0,
236 XMIT_SZ_16BIT = 1,
237 XMIT_SZ_32BIT = 2,
238 XMIT_SZ_64BIT = 7,
239 XMIT_SZ_128BIT = 3,
240 XMIT_SZ_256BIT = 4,
241 XMIT_SZ_512BIT = 5,
242};
243
244/* log2(size / 8) - used to calculate number of transfers */
245#define TS_SHIFT { \
246 [XMIT_SZ_8BIT] = 0, \
247 [XMIT_SZ_16BIT] = 1, \
248 [XMIT_SZ_32BIT] = 2, \
249 [XMIT_SZ_64BIT] = 3, \
250 [XMIT_SZ_128BIT] = 4, \
251 [XMIT_SZ_256BIT] = 5, \
252 [XMIT_SZ_512BIT] = 6, \
253}
254
255#define TS_INDEX2VAL(i) ((((i) & 3) << 3) | \
256 (((i) & 0xc) << (20 - 2)))
257
258static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = {
259 {
260 .slave_id = SHDMA_SLAVE_SCIF0_TX,
261 .addr = 0xe6c40020,
262 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
263 .mid_rid = 0x21,
264 }, {
265 .slave_id = SHDMA_SLAVE_SCIF0_RX,
266 .addr = 0xe6c40024,
267 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
268 .mid_rid = 0x22,
269 }, {
270 .slave_id = SHDMA_SLAVE_SCIF1_TX,
271 .addr = 0xe6c50020,
272 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
273 .mid_rid = 0x25,
274 }, {
275 .slave_id = SHDMA_SLAVE_SCIF1_RX,
276 .addr = 0xe6c50024,
277 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
278 .mid_rid = 0x26,
279 }, {
280 .slave_id = SHDMA_SLAVE_SCIF2_TX,
281 .addr = 0xe6c60020,
282 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
283 .mid_rid = 0x29,
284 }, {
285 .slave_id = SHDMA_SLAVE_SCIF2_RX,
286 .addr = 0xe6c60024,
287 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
288 .mid_rid = 0x2a,
289 }, {
290 .slave_id = SHDMA_SLAVE_SCIF3_TX,
291 .addr = 0xe6c70020,
292 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
293 .mid_rid = 0x2d,
294 }, {
295 .slave_id = SHDMA_SLAVE_SCIF3_RX,
296 .addr = 0xe6c70024,
297 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
298 .mid_rid = 0x2e,
299 }, {
300 .slave_id = SHDMA_SLAVE_SCIF4_TX,
301 .addr = 0xe6c80020,
302 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
303 .mid_rid = 0x39,
304 }, {
305 .slave_id = SHDMA_SLAVE_SCIF4_RX,
306 .addr = 0xe6c80024,
307 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
308 .mid_rid = 0x3a,
309 }, {
310 .slave_id = SHDMA_SLAVE_SCIF5_TX,
311 .addr = 0xe6cb0020,
312 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
313 .mid_rid = 0x35,
314 }, {
315 .slave_id = SHDMA_SLAVE_SCIF5_RX,
316 .addr = 0xe6cb0024,
317 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
318 .mid_rid = 0x36,
319 }, {
320 .slave_id = SHDMA_SLAVE_SCIF6_TX,
321 .addr = 0xe6c30040,
322 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
323 .mid_rid = 0x3d,
324 }, {
325 .slave_id = SHDMA_SLAVE_SCIF6_RX,
326 .addr = 0xe6c30060,
327 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
328 .mid_rid = 0x3e,
329 }, {
330 .slave_id = SHDMA_SLAVE_SDHI0_TX,
331 .addr = 0xe6850030,
332 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
333 .mid_rid = 0xc1,
334 }, {
335 .slave_id = SHDMA_SLAVE_SDHI0_RX,
336 .addr = 0xe6850030,
337 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
338 .mid_rid = 0xc2,
339 }, {
340 .slave_id = SHDMA_SLAVE_SDHI1_TX,
341 .addr = 0xe6860030,
342 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
343 .mid_rid = 0xc9,
344 }, {
345 .slave_id = SHDMA_SLAVE_SDHI1_RX,
346 .addr = 0xe6860030,
347 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
348 .mid_rid = 0xca,
349 }, {
350 .slave_id = SHDMA_SLAVE_SDHI2_TX,
351 .addr = 0xe6870030,
352 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
353 .mid_rid = 0xcd,
354 }, {
355 .slave_id = SHDMA_SLAVE_SDHI2_RX,
356 .addr = 0xe6870030,
357 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
358 .mid_rid = 0xce,
359 },
360};
361
362static const struct sh_dmae_channel sh7372_dmae_channels[] = {
363 {
364 .offset = 0,
365 .dmars = 0,
366 .dmars_bit = 0,
367 }, {
368 .offset = 0x10,
369 .dmars = 0,
370 .dmars_bit = 8,
371 }, {
372 .offset = 0x20,
373 .dmars = 4,
374 .dmars_bit = 0,
375 }, {
376 .offset = 0x30,
377 .dmars = 4,
378 .dmars_bit = 8,
379 }, {
380 .offset = 0x50,
381 .dmars = 8,
382 .dmars_bit = 0,
383 }, {
384 .offset = 0x60,
385 .dmars = 8,
386 .dmars_bit = 8,
387 }
388};
389
390static const unsigned int ts_shift[] = TS_SHIFT;
391
392static struct sh_dmae_pdata dma_platform_data = {
393 .slave = sh7372_dmae_slaves,
394 .slave_num = ARRAY_SIZE(sh7372_dmae_slaves),
395 .channel = sh7372_dmae_channels,
396 .channel_num = ARRAY_SIZE(sh7372_dmae_channels),
397 .ts_low_shift = 3,
398 .ts_low_mask = 0x18,
399 .ts_high_shift = (20 - 2), /* 2 bits for shifted low TS */
400 .ts_high_mask = 0x00300000,
401 .ts_shift = ts_shift,
402 .ts_shift_num = ARRAY_SIZE(ts_shift),
403 .dmaor_init = DMAOR_DME,
404};
405
406/* Resource order important! */
407static struct resource sh7372_dmae0_resources[] = {
408 {
409 /* Channel registers and DMAOR */
410 .start = 0xfe008020,
411 .end = 0xfe00808f,
412 .flags = IORESOURCE_MEM,
413 },
414 {
415 /* DMARSx */
416 .start = 0xfe009000,
417 .end = 0xfe00900b,
418 .flags = IORESOURCE_MEM,
419 },
420 {
421 /* DMA error IRQ */
422 .start = 246,
423 .end = 246,
424 .flags = IORESOURCE_IRQ,
425 },
426 {
427 /* IRQ for channels 0-5 */
428 .start = 240,
429 .end = 245,
430 .flags = IORESOURCE_IRQ,
431 },
432};
433
434/* Resource order important! */
435static struct resource sh7372_dmae1_resources[] = {
436 {
437 /* Channel registers and DMAOR */
438 .start = 0xfe018020,
439 .end = 0xfe01808f,
440 .flags = IORESOURCE_MEM,
441 },
442 {
443 /* DMARSx */
444 .start = 0xfe019000,
445 .end = 0xfe01900b,
446 .flags = IORESOURCE_MEM,
447 },
448 {
449 /* DMA error IRQ */
450 .start = 254,
451 .end = 254,
452 .flags = IORESOURCE_IRQ,
453 },
454 {
455 /* IRQ for channels 0-5 */
456 .start = 248,
457 .end = 253,
458 .flags = IORESOURCE_IRQ,
459 },
460};
461
462/* Resource order important! */
463static struct resource sh7372_dmae2_resources[] = {
464 {
465 /* Channel registers and DMAOR */
466 .start = 0xfe028020,
467 .end = 0xfe02808f,
468 .flags = IORESOURCE_MEM,
469 },
470 {
471 /* DMARSx */
472 .start = 0xfe029000,
473 .end = 0xfe02900b,
474 .flags = IORESOURCE_MEM,
475 },
476 {
477 /* DMA error IRQ */
478 .start = 262,
479 .end = 262,
480 .flags = IORESOURCE_IRQ,
481 },
482 {
483 /* IRQ for channels 0-5 */
484 .start = 256,
485 .end = 261,
486 .flags = IORESOURCE_IRQ,
487 },
488};
489
490static struct platform_device dma0_device = {
491 .name = "sh-dma-engine",
492 .id = 0,
493 .resource = sh7372_dmae0_resources,
494 .num_resources = ARRAY_SIZE(sh7372_dmae0_resources),
495 .dev = {
496 .platform_data = &dma_platform_data,
497 },
498};
499
500static struct platform_device dma1_device = {
501 .name = "sh-dma-engine",
502 .id = 1,
503 .resource = sh7372_dmae1_resources,
504 .num_resources = ARRAY_SIZE(sh7372_dmae1_resources),
505 .dev = {
506 .platform_data = &dma_platform_data,
507 },
508};
509
510static struct platform_device dma2_device = {
511 .name = "sh-dma-engine",
512 .id = 2,
513 .resource = sh7372_dmae2_resources,
514 .num_resources = ARRAY_SIZE(sh7372_dmae2_resources),
515 .dev = {
516 .platform_data = &dma_platform_data,
517 },
518};
519
172static struct platform_device *sh7372_early_devices[] __initdata = { 520static struct platform_device *sh7372_early_devices[] __initdata = {
173 &scif0_device, 521 &scif0_device,
174 &scif1_device, 522 &scif1_device,
@@ -178,6 +526,11 @@ static struct platform_device *sh7372_early_devices[] __initdata = {
178 &scif5_device, 526 &scif5_device,
179 &scif6_device, 527 &scif6_device,
180 &cmt10_device, 528 &cmt10_device,
529 &iic0_device,
530 &iic1_device,
531 &dma0_device,
532 &dma1_device,
533 &dma2_device,
181}; 534};
182 535
183void __init sh7372_add_standard_devices(void) 536void __init sh7372_add_standard_devices(void)
@@ -186,14 +539,8 @@ void __init sh7372_add_standard_devices(void)
186 ARRAY_SIZE(sh7372_early_devices)); 539 ARRAY_SIZE(sh7372_early_devices));
187} 540}
188 541
189#define SMSTPCR3 0xe615013c
190#define SMSTPCR3_CMT1 (1 << 29)
191
192void __init sh7372_add_early_devices(void) 542void __init sh7372_add_early_devices(void)
193{ 543{
194 /* enable clock to CMT1 */
195 __raw_writel(__raw_readl(SMSTPCR3) & ~SMSTPCR3_CMT1, SMSTPCR3);
196
197 early_platform_add_devices(sh7372_early_devices, 544 early_platform_add_devices(sh7372_early_devices,
198 ARRAY_SIZE(sh7372_early_devices)); 545 ARRAY_SIZE(sh7372_early_devices));
199} 546}
diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c
index 60e37774c35..bb4adf17dbf 100644
--- a/arch/arm/mach-shmobile/setup-sh7377.c
+++ b/arch/arm/mach-shmobile/setup-sh7377.c
@@ -32,11 +32,13 @@
32#include <asm/mach-types.h> 32#include <asm/mach-types.h>
33#include <asm/mach/arch.h> 33#include <asm/mach/arch.h>
34 34
35/* SCIFA0 */
35static struct plat_sci_port scif0_platform_data = { 36static struct plat_sci_port scif0_platform_data = {
36 .mapbase = 0xe6c40000, 37 .mapbase = 0xe6c40000,
37 .flags = UPF_BOOT_AUTOCONF, 38 .flags = UPF_BOOT_AUTOCONF,
38 .type = PORT_SCIF, 39 .type = PORT_SCIF,
39 .irqs = { 80, 80, 80, 80 }, 40 .irqs = { evt2irq(0xc00), evt2irq(0xc00),
41 evt2irq(0xc00), evt2irq(0xc00) },
40}; 42};
41 43
42static struct platform_device scif0_device = { 44static struct platform_device scif0_device = {
@@ -47,11 +49,13 @@ static struct platform_device scif0_device = {
47 }, 49 },
48}; 50};
49 51
52/* SCIFA1 */
50static struct plat_sci_port scif1_platform_data = { 53static struct plat_sci_port scif1_platform_data = {
51 .mapbase = 0xe6c50000, 54 .mapbase = 0xe6c50000,
52 .flags = UPF_BOOT_AUTOCONF, 55 .flags = UPF_BOOT_AUTOCONF,
53 .type = PORT_SCIF, 56 .type = PORT_SCIF,
54 .irqs = { 81, 81, 81, 81 }, 57 .irqs = { evt2irq(0xc20), evt2irq(0xc20),
58 evt2irq(0xc20), evt2irq(0xc20) },
55}; 59};
56 60
57static struct platform_device scif1_device = { 61static struct platform_device scif1_device = {
@@ -62,11 +66,13 @@ static struct platform_device scif1_device = {
62 }, 66 },
63}; 67};
64 68
69/* SCIFA2 */
65static struct plat_sci_port scif2_platform_data = { 70static struct plat_sci_port scif2_platform_data = {
66 .mapbase = 0xe6c60000, 71 .mapbase = 0xe6c60000,
67 .flags = UPF_BOOT_AUTOCONF, 72 .flags = UPF_BOOT_AUTOCONF,
68 .type = PORT_SCIF, 73 .type = PORT_SCIF,
69 .irqs = { 82, 82, 82, 82 }, 74 .irqs = { evt2irq(0xc40), evt2irq(0xc40),
75 evt2irq(0xc40), evt2irq(0xc40) },
70}; 76};
71 77
72static struct platform_device scif2_device = { 78static struct platform_device scif2_device = {
@@ -77,11 +83,13 @@ static struct platform_device scif2_device = {
77 }, 83 },
78}; 84};
79 85
86/* SCIFA3 */
80static struct plat_sci_port scif3_platform_data = { 87static struct plat_sci_port scif3_platform_data = {
81 .mapbase = 0xe6c70000, 88 .mapbase = 0xe6c70000,
82 .flags = UPF_BOOT_AUTOCONF, 89 .flags = UPF_BOOT_AUTOCONF,
83 .type = PORT_SCIF, 90 .type = PORT_SCIF,
84 .irqs = { 83, 83, 83, 83 }, 91 .irqs = { evt2irq(0xc60), evt2irq(0xc60),
92 evt2irq(0xc60), evt2irq(0xc60) },
85}; 93};
86 94
87static struct platform_device scif3_device = { 95static struct platform_device scif3_device = {
@@ -92,11 +100,13 @@ static struct platform_device scif3_device = {
92 }, 100 },
93}; 101};
94 102
103/* SCIFA4 */
95static struct plat_sci_port scif4_platform_data = { 104static struct plat_sci_port scif4_platform_data = {
96 .mapbase = 0xe6c80000, 105 .mapbase = 0xe6c80000,
97 .flags = UPF_BOOT_AUTOCONF, 106 .flags = UPF_BOOT_AUTOCONF,
98 .type = PORT_SCIF, 107 .type = PORT_SCIF,
99 .irqs = { 89, 89, 89, 89 }, 108 .irqs = { evt2irq(0xd20), evt2irq(0xd20),
109 evt2irq(0xd20), evt2irq(0xd20) },
100}; 110};
101 111
102static struct platform_device scif4_device = { 112static struct platform_device scif4_device = {
@@ -107,11 +117,13 @@ static struct platform_device scif4_device = {
107 }, 117 },
108}; 118};
109 119
120/* SCIFA5 */
110static struct plat_sci_port scif5_platform_data = { 121static struct plat_sci_port scif5_platform_data = {
111 .mapbase = 0xe6cb0000, 122 .mapbase = 0xe6cb0000,
112 .flags = UPF_BOOT_AUTOCONF, 123 .flags = UPF_BOOT_AUTOCONF,
113 .type = PORT_SCIF, 124 .type = PORT_SCIF,
114 .irqs = { 90, 90, 90, 90 }, 125 .irqs = { evt2irq(0xd40), evt2irq(0xd40),
126 evt2irq(0xd40), evt2irq(0xd40) },
115}; 127};
116 128
117static struct platform_device scif5_device = { 129static struct platform_device scif5_device = {
@@ -122,11 +134,13 @@ static struct platform_device scif5_device = {
122 }, 134 },
123}; 135};
124 136
137/* SCIFA6 */
125static struct plat_sci_port scif6_platform_data = { 138static struct plat_sci_port scif6_platform_data = {
126 .mapbase = 0xe6cc0000, 139 .mapbase = 0xe6cc0000,
127 .flags = UPF_BOOT_AUTOCONF, 140 .flags = UPF_BOOT_AUTOCONF,
128 .type = PORT_SCIF, 141 .type = PORT_SCIF,
129 .irqs = { 196, 196, 196, 196 }, 142 .irqs = { intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80),
143 intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80) },
130}; 144};
131 145
132static struct platform_device scif6_device = { 146static struct platform_device scif6_device = {
@@ -137,11 +151,13 @@ static struct platform_device scif6_device = {
137 }, 151 },
138}; 152};
139 153
154/* SCIFB */
140static struct plat_sci_port scif7_platform_data = { 155static struct plat_sci_port scif7_platform_data = {
141 .mapbase = 0xe6c30000, 156 .mapbase = 0xe6c30000,
142 .flags = UPF_BOOT_AUTOCONF, 157 .flags = UPF_BOOT_AUTOCONF,
143 .type = PORT_SCIF, 158 .type = PORT_SCIF,
144 .irqs = { 91, 91, 91, 91 }, 159 .irqs = { evt2irq(0xd60), evt2irq(0xd60),
160 evt2irq(0xd60), evt2irq(0xd60) },
145}; 161};
146 162
147static struct platform_device scif7_device = { 163static struct platform_device scif7_device = {
@@ -169,7 +185,7 @@ static struct resource cmt10_resources[] = {
169 .flags = IORESOURCE_MEM, 185 .flags = IORESOURCE_MEM,
170 }, 186 },
171 [1] = { 187 [1] = {
172 .start = 72, 188 .start = evt2irq(0xb00), /* CMT1_CMT10 */
173 .flags = IORESOURCE_IRQ, 189 .flags = IORESOURCE_IRQ,
174 }, 190 },
175}; 191};
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index de375b64e41..3da116f47f0 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -154,7 +154,7 @@ static struct platform_device nand_flash_device = {
154#define PORT_DRVCRA 0xA405018A 154#define PORT_DRVCRA 0xA405018A
155#define PORT_DRVCRB 0xA405018C 155#define PORT_DRVCRB 0xA405018C
156 156
157static void ap320_wvga_power_on(void *board_data) 157static void ap320_wvga_power_on(void *board_data, struct fb_info *info)
158{ 158{
159 msleep(100); 159 msleep(100);
160 160
diff --git a/arch/sh/boards/mach-kfr2r09/Makefile b/arch/sh/boards/mach-kfr2r09/Makefile
index 4e577a3bf65..60dd63f4a42 100644
--- a/arch/sh/boards/mach-kfr2r09/Makefile
+++ b/arch/sh/boards/mach-kfr2r09/Makefile
@@ -1,2 +1,4 @@
1obj-y := setup.o sdram.o 1obj-y := setup.o sdram.o
2obj-$(CONFIG_FB_SH_MOBILE_LCDC) += lcd_wqvga.o 2ifneq ($(CONFIG_FB_SH_MOBILE_LCDC),)
3obj-y += lcd_wqvga.o
4endif
diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
index e9b970846c4..25e145fb708 100644
--- a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
+++ b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
@@ -327,7 +327,7 @@ static int kfr2r09_lcd_backlight(int on)
327 return 0; 327 return 0;
328} 328}
329 329
330void kfr2r09_lcd_on(void *board_data) 330void kfr2r09_lcd_on(void *board_data, struct fb_info *info)
331{ 331{
332 kfr2r09_lcd_backlight(1); 332 kfr2r09_lcd_backlight(1);
333} 333}
diff --git a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
index 484ef42c2fb..07e635b0e04 100644
--- a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
+++ b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
@@ -3,23 +3,23 @@
3 3
4#include <video/sh_mobile_lcdc.h> 4#include <video/sh_mobile_lcdc.h>
5 5
6#ifdef CONFIG_FB_SH_MOBILE_LCDC 6#if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE)
7void kfr2r09_lcd_on(void *board_data); 7void kfr2r09_lcd_on(void *board_data, struct fb_info *info);
8void kfr2r09_lcd_off(void *board_data); 8void kfr2r09_lcd_off(void *board_data);
9int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle, 9int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle,
10 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 10 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
11void kfr2r09_lcd_start(void *board_data, void *sys_ops_handle, 11void kfr2r09_lcd_start(void *board_data, void *sys_ops_handle,
12 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 12 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
13#else 13#else
14static inline void kfr2r09_lcd_on(void *board_data) {} 14static void kfr2r09_lcd_on(void *board_data) {}
15static inline void kfr2r09_lcd_off(void *board_data) {} 15static void kfr2r09_lcd_off(void *board_data) {}
16static inline int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle, 16static int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle,
17 struct sh_mobile_lcdc_sys_bus_ops *sys_ops) 17 struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
18{ 18{
19 return -ENODEV; 19 return -ENODEV;
20} 20}
21static inline void kfr2r09_lcd_start(void *board_data, void *sys_ops_handle, 21static void kfr2r09_lcd_start(void *board_data, void *sys_ops_handle,
22 struct sh_mobile_lcdc_sys_bus_ops *sys_ops) 22 struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
23{ 23{
24} 24}
25#endif 25#endif
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 9e01e96fee9..8344375dc01 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -128,7 +128,7 @@ config TXX9_DMAC
128 128
129config SH_DMAE 129config SH_DMAE
130 tristate "Renesas SuperH DMAC support" 130 tristate "Renesas SuperH DMAC support"
131 depends on SUPERH && SH_DMA 131 depends on (SUPERH && SH_DMA) || (ARM && ARCH_SHMOBILE)
132 depends on !SH_DMA_API 132 depends on !SH_DMA_API
133 select DMA_ENGINE 133 select DMA_ENGINE
134 help 134 help
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index a2a519fd2a2..fb64cf36ba6 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -816,7 +816,7 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data)
816 return ret; 816 return ret;
817} 817}
818 818
819#if defined(CONFIG_CPU_SH4) 819#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
820static irqreturn_t sh_dmae_err(int irq, void *data) 820static irqreturn_t sh_dmae_err(int irq, void *data)
821{ 821{
822 struct sh_dmae_device *shdev = (struct sh_dmae_device *)data; 822 struct sh_dmae_device *shdev = (struct sh_dmae_device *)data;
@@ -1057,7 +1057,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
1057 /* Default transfer size of 32 bytes requires 32-byte alignment */ 1057 /* Default transfer size of 32 bytes requires 32-byte alignment */
1058 shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE; 1058 shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;
1059 1059
1060#if defined(CONFIG_CPU_SH4) 1060#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
1061 chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); 1061 chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
1062 1062
1063 if (!chanirq_res) 1063 if (!chanirq_res)
@@ -1082,7 +1082,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
1082 1082
1083#else 1083#else
1084 chanirq_res = errirq_res; 1084 chanirq_res = errirq_res;
1085#endif /* CONFIG_CPU_SH4 */ 1085#endif /* CONFIG_CPU_SH4 || CONFIG_ARCH_SHMOBILE */
1086 1086
1087 if (chanirq_res->start == chanirq_res->end && 1087 if (chanirq_res->start == chanirq_res->end &&
1088 !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { 1088 !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
@@ -1129,7 +1129,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
1129chan_probe_err: 1129chan_probe_err:
1130 sh_dmae_chan_remove(shdev); 1130 sh_dmae_chan_remove(shdev);
1131eirqres: 1131eirqres:
1132#if defined(CONFIG_CPU_SH4) 1132#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
1133 free_irq(errirq, shdev); 1133 free_irq(errirq, shdev);
1134eirq_err: 1134eirq_err:
1135#endif 1135#endif
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index bceafbfa726..29e01f6238a 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -549,7 +549,7 @@ config I2C_SH7760
549 549
550config I2C_SH_MOBILE 550config I2C_SH_MOBILE
551 tristate "SuperH Mobile I2C Controller" 551 tristate "SuperH Mobile I2C Controller"
552 depends on SUPERH 552 depends on SUPERH || ARCH_SHMOBILE
553 help 553 help
554 If you say yes to this option, support will be included for the 554 If you say yes to this option, support will be included for the
555 built-in I2C interface on the Renesas SH-Mobile processor. 555 built-in I2C interface on the Renesas SH-Mobile processor.
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index ffb405d7c6f..598c49acaeb 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -119,8 +119,10 @@ struct sh_mobile_i2c_data {
119 struct i2c_adapter adap; 119 struct i2c_adapter adap;
120 120
121 struct clk *clk; 121 struct clk *clk;
122 u_int8_t icic;
122 u_int8_t iccl; 123 u_int8_t iccl;
123 u_int8_t icch; 124 u_int8_t icch;
125 u_int8_t flags;
124 126
125 spinlock_t lock; 127 spinlock_t lock;
126 wait_queue_head_t wait; 128 wait_queue_head_t wait;
@@ -129,15 +131,17 @@ struct sh_mobile_i2c_data {
129 int sr; 131 int sr;
130}; 132};
131 133
134#define IIC_FLAG_HAS_ICIC67 (1 << 0)
135
132#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ 136#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */
133 137
134/* Register offsets */ 138/* Register offsets */
135#define ICDR(pd) (pd->reg + 0x00) 139#define ICDR 0x00
136#define ICCR(pd) (pd->reg + 0x04) 140#define ICCR 0x04
137#define ICSR(pd) (pd->reg + 0x08) 141#define ICSR 0x08
138#define ICIC(pd) (pd->reg + 0x0c) 142#define ICIC 0x0c
139#define ICCL(pd) (pd->reg + 0x10) 143#define ICCL 0x10
140#define ICCH(pd) (pd->reg + 0x14) 144#define ICCH 0x14
141 145
142/* Register bits */ 146/* Register bits */
143#define ICCR_ICE 0x80 147#define ICCR_ICE 0x80
@@ -155,11 +159,32 @@ struct sh_mobile_i2c_data {
155#define ICSR_WAIT 0x02 159#define ICSR_WAIT 0x02
156#define ICSR_DTE 0x01 160#define ICSR_DTE 0x01
157 161
162#define ICIC_ICCLB8 0x80
163#define ICIC_ICCHB8 0x40
158#define ICIC_ALE 0x08 164#define ICIC_ALE 0x08
159#define ICIC_TACKE 0x04 165#define ICIC_TACKE 0x04
160#define ICIC_WAITE 0x02 166#define ICIC_WAITE 0x02
161#define ICIC_DTEE 0x01 167#define ICIC_DTEE 0x01
162 168
169static void iic_wr(struct sh_mobile_i2c_data *pd, int offs, unsigned char data)
170{
171 if (offs == ICIC)
172 data |= pd->icic;
173
174 iowrite8(data, pd->reg + offs);
175}
176
177static unsigned char iic_rd(struct sh_mobile_i2c_data *pd, int offs)
178{
179 return ioread8(pd->reg + offs);
180}
181
182static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs,
183 unsigned char set, unsigned char clr)
184{
185 iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr);
186}
187
163static void activate_ch(struct sh_mobile_i2c_data *pd) 188static void activate_ch(struct sh_mobile_i2c_data *pd)
164{ 189{
165 unsigned long i2c_clk; 190 unsigned long i2c_clk;
@@ -187,6 +212,14 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)
187 else 212 else
188 pd->iccl = (u_int8_t)(num/denom); 213 pd->iccl = (u_int8_t)(num/denom);
189 214
215 /* one more bit of ICCL in ICIC */
216 if (pd->flags & IIC_FLAG_HAS_ICIC67) {
217 if ((num/denom) > 0xff)
218 pd->icic |= ICIC_ICCLB8;
219 else
220 pd->icic &= ~ICIC_ICCLB8;
221 }
222
190 /* Calculate the value for icch. From the data sheet: 223 /* Calculate the value for icch. From the data sheet:
191 icch = (p clock / transfer rate) * (H / (L + H)) */ 224 icch = (p clock / transfer rate) * (H / (L + H)) */
192 num = i2c_clk * 4; 225 num = i2c_clk * 4;
@@ -196,25 +229,33 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)
196 else 229 else
197 pd->icch = (u_int8_t)(num/denom); 230 pd->icch = (u_int8_t)(num/denom);
198 231
232 /* one more bit of ICCH in ICIC */
233 if (pd->flags & IIC_FLAG_HAS_ICIC67) {
234 if ((num/denom) > 0xff)
235 pd->icic |= ICIC_ICCHB8;
236 else
237 pd->icic &= ~ICIC_ICCHB8;
238 }
239
199 /* Enable channel and configure rx ack */ 240 /* Enable channel and configure rx ack */
200 iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); 241 iic_set_clr(pd, ICCR, ICCR_ICE, 0);
201 242
202 /* Mask all interrupts */ 243 /* Mask all interrupts */
203 iowrite8(0, ICIC(pd)); 244 iic_wr(pd, ICIC, 0);
204 245
205 /* Set the clock */ 246 /* Set the clock */
206 iowrite8(pd->iccl, ICCL(pd)); 247 iic_wr(pd, ICCL, pd->iccl);
207 iowrite8(pd->icch, ICCH(pd)); 248 iic_wr(pd, ICCH, pd->icch);
208} 249}
209 250
210static void deactivate_ch(struct sh_mobile_i2c_data *pd) 251static void deactivate_ch(struct sh_mobile_i2c_data *pd)
211{ 252{
212 /* Clear/disable interrupts */ 253 /* Clear/disable interrupts */
213 iowrite8(0, ICSR(pd)); 254 iic_wr(pd, ICSR, 0);
214 iowrite8(0, ICIC(pd)); 255 iic_wr(pd, ICIC, 0);
215 256
216 /* Disable channel */ 257 /* Disable channel */
217 iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); 258 iic_set_clr(pd, ICCR, 0, ICCR_ICE);
218 259
219 /* Disable clock and mark device as idle */ 260 /* Disable clock and mark device as idle */
220 clk_disable(pd->clk); 261 clk_disable(pd->clk);
@@ -233,35 +274,35 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
233 274
234 switch (op) { 275 switch (op) {
235 case OP_START: /* issue start and trigger DTE interrupt */ 276 case OP_START: /* issue start and trigger DTE interrupt */
236 iowrite8(0x94, ICCR(pd)); 277 iic_wr(pd, ICCR, 0x94);
237 break; 278 break;
238 case OP_TX_FIRST: /* disable DTE interrupt and write data */ 279 case OP_TX_FIRST: /* disable DTE interrupt and write data */
239 iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE, ICIC(pd)); 280 iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
240 iowrite8(data, ICDR(pd)); 281 iic_wr(pd, ICDR, data);
241 break; 282 break;
242 case OP_TX: /* write data */ 283 case OP_TX: /* write data */
243 iowrite8(data, ICDR(pd)); 284 iic_wr(pd, ICDR, data);
244 break; 285 break;
245 case OP_TX_STOP: /* write data and issue a stop afterwards */ 286 case OP_TX_STOP: /* write data and issue a stop afterwards */
246 iowrite8(data, ICDR(pd)); 287 iic_wr(pd, ICDR, data);
247 iowrite8(0x90, ICCR(pd)); 288 iic_wr(pd, ICCR, 0x90);
248 break; 289 break;
249 case OP_TX_TO_RX: /* select read mode */ 290 case OP_TX_TO_RX: /* select read mode */
250 iowrite8(0x81, ICCR(pd)); 291 iic_wr(pd, ICCR, 0x81);
251 break; 292 break;
252 case OP_RX: /* just read data */ 293 case OP_RX: /* just read data */
253 ret = ioread8(ICDR(pd)); 294 ret = iic_rd(pd, ICDR);
254 break; 295 break;
255 case OP_RX_STOP: /* enable DTE interrupt, issue stop */ 296 case OP_RX_STOP: /* enable DTE interrupt, issue stop */
256 iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, 297 iic_wr(pd, ICIC,
257 ICIC(pd)); 298 ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
258 iowrite8(0xc0, ICCR(pd)); 299 iic_wr(pd, ICCR, 0xc0);
259 break; 300 break;
260 case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ 301 case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */
261 iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, 302 iic_wr(pd, ICIC,
262 ICIC(pd)); 303 ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
263 ret = ioread8(ICDR(pd)); 304 ret = iic_rd(pd, ICDR);
264 iowrite8(0xc0, ICCR(pd)); 305 iic_wr(pd, ICCR, 0xc0);
265 break; 306 break;
266 } 307 }
267 308
@@ -367,7 +408,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
367 unsigned char sr; 408 unsigned char sr;
368 int wakeup; 409 int wakeup;
369 410
370 sr = ioread8(ICSR(pd)); 411 sr = iic_rd(pd, ICSR);
371 pd->sr |= sr; /* remember state */ 412 pd->sr |= sr; /* remember state */
372 413
373 dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr, 414 dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr,
@@ -376,7 +417,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
376 417
377 if (sr & (ICSR_AL | ICSR_TACK)) { 418 if (sr & (ICSR_AL | ICSR_TACK)) {
378 /* don't interrupt transaction - continue to issue stop */ 419 /* don't interrupt transaction - continue to issue stop */
379 iowrite8(sr & ~(ICSR_AL | ICSR_TACK), ICSR(pd)); 420 iic_wr(pd, ICSR, sr & ~(ICSR_AL | ICSR_TACK));
380 wakeup = 0; 421 wakeup = 0;
381 } else if (pd->msg->flags & I2C_M_RD) 422 } else if (pd->msg->flags & I2C_M_RD)
382 wakeup = sh_mobile_i2c_isr_rx(pd); 423 wakeup = sh_mobile_i2c_isr_rx(pd);
@@ -384,7 +425,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
384 wakeup = sh_mobile_i2c_isr_tx(pd); 425 wakeup = sh_mobile_i2c_isr_tx(pd);
385 426
386 if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */ 427 if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */
387 iowrite8(sr & ~ICSR_WAIT, ICSR(pd)); 428 iic_wr(pd, ICSR, sr & ~ICSR_WAIT);
388 429
389 if (wakeup) { 430 if (wakeup) {
390 pd->sr |= SW_DONE; 431 pd->sr |= SW_DONE;
@@ -402,21 +443,21 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
402 } 443 }
403 444
404 /* Initialize channel registers */ 445 /* Initialize channel registers */
405 iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); 446 iic_set_clr(pd, ICCR, 0, ICCR_ICE);
406 447
407 /* Enable channel and configure rx ack */ 448 /* Enable channel and configure rx ack */
408 iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); 449 iic_set_clr(pd, ICCR, ICCR_ICE, 0);
409 450
410 /* Set the clock */ 451 /* Set the clock */
411 iowrite8(pd->iccl, ICCL(pd)); 452 iic_wr(pd, ICCL, pd->iccl);
412 iowrite8(pd->icch, ICCH(pd)); 453 iic_wr(pd, ICCH, pd->icch);
413 454
414 pd->msg = usr_msg; 455 pd->msg = usr_msg;
415 pd->pos = -1; 456 pd->pos = -1;
416 pd->sr = 0; 457 pd->sr = 0;
417 458
418 /* Enable all interrupts to begin with */ 459 /* Enable all interrupts to begin with */
419 iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE | ICIC_DTEE, ICIC(pd)); 460 iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
420 return 0; 461 return 0;
421} 462}
422 463
@@ -451,7 +492,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
451 492
452 retry_count = 1000; 493 retry_count = 1000;
453again: 494again:
454 val = ioread8(ICSR(pd)); 495 val = iic_rd(pd, ICSR);
455 496
456 dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr); 497 dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
457 498
@@ -576,6 +617,12 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
576 goto err_irq; 617 goto err_irq;
577 } 618 }
578 619
620 /* The IIC blocks on SH-Mobile ARM processors
621 * come with two new bits in ICIC.
622 */
623 if (size > 0x17)
624 pd->flags |= IIC_FLAG_HAS_ICIC67;
625
579 /* Enable Runtime PM for this device. 626 /* Enable Runtime PM for this device.
580 * 627 *
581 * Also tell the Runtime PM core to ignore children 628 * Also tell the Runtime PM core to ignore children
diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c
index edd5666f0ff..9e3f4f54281 100644
--- a/drivers/net/irda/sh_irda.c
+++ b/drivers/net/irda/sh_irda.c
@@ -748,7 +748,6 @@ static int __devinit sh_irda_probe(struct platform_device *pdev)
748 struct net_device *ndev; 748 struct net_device *ndev;
749 struct sh_irda_self *self; 749 struct sh_irda_self *self;
750 struct resource *res; 750 struct resource *res;
751 char clk_name[8];
752 int irq; 751 int irq;
753 int err = -ENOMEM; 752 int err = -ENOMEM;
754 753
@@ -775,10 +774,9 @@ static int __devinit sh_irda_probe(struct platform_device *pdev)
775 if (err) 774 if (err)
776 goto err_mem_2; 775 goto err_mem_2;
777 776
778 snprintf(clk_name, sizeof(clk_name), "irda%d", pdev->id); 777 self->clk = clk_get(&pdev->dev, NULL);
779 self->clk = clk_get(&pdev->dev, clk_name);
780 if (IS_ERR(self->clk)) { 778 if (IS_ERR(self->clk)) {
781 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); 779 dev_err(&pdev->dev, "cannot get irda clock\n");
782 goto err_mem_3; 780 goto err_mem_3;
783 } 781 }
784 782
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 5f90fcd7d10..c291b3add1d 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -346,6 +346,27 @@ static int scif_rxfill(struct uart_port *port)
346 return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; 346 return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
347 } 347 }
348} 348}
349#elif defined(CONFIG_ARCH_SH7372)
350static int scif_txfill(struct uart_port *port)
351{
352 if (port->type == PORT_SCIFA)
353 return sci_in(port, SCFDR) >> 8;
354 else
355 return sci_in(port, SCTFDR);
356}
357
358static int scif_txroom(struct uart_port *port)
359{
360 return port->fifosize - scif_txfill(port);
361}
362
363static int scif_rxfill(struct uart_port *port)
364{
365 if (port->type == PORT_SCIFA)
366 return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
367 else
368 return sci_in(port, SCRFDR);
369}
349#else 370#else
350static int scif_txfill(struct uart_port *port) 371static int scif_txfill(struct uart_port *port)
351{ 372{
@@ -683,7 +704,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
683 u16 ssr = sci_in(port, SCxSR); 704 u16 ssr = sci_in(port, SCxSR);
684 705
685 /* Disable future Rx interrupts */ 706 /* Disable future Rx interrupts */
686 if (port->type == PORT_SCIFA) { 707 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
687 disable_irq_nosync(irq); 708 disable_irq_nosync(irq);
688 scr |= 0x4000; 709 scr |= 0x4000;
689 } else { 710 } else {
@@ -928,7 +949,7 @@ static void sci_dma_tx_complete(void *arg)
928 949
929 if (!uart_circ_empty(xmit)) { 950 if (!uart_circ_empty(xmit)) {
930 schedule_work(&s->work_tx); 951 schedule_work(&s->work_tx);
931 } else if (port->type == PORT_SCIFA) { 952 } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
932 u16 ctrl = sci_in(port, SCSCR); 953 u16 ctrl = sci_in(port, SCSCR);
933 sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); 954 sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE);
934 } 955 }
@@ -1184,7 +1205,7 @@ static void sci_start_tx(struct uart_port *port)
1184 unsigned short ctrl; 1205 unsigned short ctrl;
1185 1206
1186#ifdef CONFIG_SERIAL_SH_SCI_DMA 1207#ifdef CONFIG_SERIAL_SH_SCI_DMA
1187 if (port->type == PORT_SCIFA) { 1208 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
1188 u16 new, scr = sci_in(port, SCSCR); 1209 u16 new, scr = sci_in(port, SCSCR);
1189 if (s->chan_tx) 1210 if (s->chan_tx)
1190 new = scr | 0x8000; 1211 new = scr | 0x8000;
@@ -1197,7 +1218,7 @@ static void sci_start_tx(struct uart_port *port)
1197 s->cookie_tx < 0) 1218 s->cookie_tx < 0)
1198 schedule_work(&s->work_tx); 1219 schedule_work(&s->work_tx);
1199#endif 1220#endif
1200 if (!s->chan_tx || port->type == PORT_SCIFA) { 1221 if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
1201 /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ 1222 /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
1202 ctrl = sci_in(port, SCSCR); 1223 ctrl = sci_in(port, SCSCR);
1203 sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); 1224 sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE);
@@ -1210,7 +1231,7 @@ static void sci_stop_tx(struct uart_port *port)
1210 1231
1211 /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ 1232 /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
1212 ctrl = sci_in(port, SCSCR); 1233 ctrl = sci_in(port, SCSCR);
1213 if (port->type == PORT_SCIFA) 1234 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
1214 ctrl &= ~0x8000; 1235 ctrl &= ~0x8000;
1215 ctrl &= ~SCI_CTRL_FLAGS_TIE; 1236 ctrl &= ~SCI_CTRL_FLAGS_TIE;
1216 sci_out(port, SCSCR, ctrl); 1237 sci_out(port, SCSCR, ctrl);
@@ -1222,7 +1243,7 @@ static void sci_start_rx(struct uart_port *port)
1222 1243
1223 /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ 1244 /* Set RIE (Receive Interrupt Enable) bit in SCSCR */
1224 ctrl |= sci_in(port, SCSCR); 1245 ctrl |= sci_in(port, SCSCR);
1225 if (port->type == PORT_SCIFA) 1246 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
1226 ctrl &= ~0x4000; 1247 ctrl &= ~0x4000;
1227 sci_out(port, SCSCR, ctrl); 1248 sci_out(port, SCSCR, ctrl);
1228} 1249}
@@ -1233,7 +1254,7 @@ static void sci_stop_rx(struct uart_port *port)
1233 1254
1234 /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ 1255 /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
1235 ctrl = sci_in(port, SCSCR); 1256 ctrl = sci_in(port, SCSCR);
1236 if (port->type == PORT_SCIFA) 1257 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
1237 ctrl &= ~0x4000; 1258 ctrl &= ~0x4000;
1238 ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); 1259 ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE);
1239 sci_out(port, SCSCR, ctrl); 1260 sci_out(port, SCSCR, ctrl);
@@ -1271,7 +1292,7 @@ static void rx_timer_fn(unsigned long arg)
1271 struct uart_port *port = &s->port; 1292 struct uart_port *port = &s->port;
1272 u16 scr = sci_in(port, SCSCR); 1293 u16 scr = sci_in(port, SCSCR);
1273 1294
1274 if (port->type == PORT_SCIFA) { 1295 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
1275 scr &= ~0x4000; 1296 scr &= ~0x4000;
1276 enable_irq(s->irqs[1]); 1297 enable_irq(s->irqs[1]);
1277 } 1298 }
@@ -1524,6 +1545,8 @@ static const char *sci_type(struct uart_port *port)
1524 return "scif"; 1545 return "scif";
1525 case PORT_SCIFA: 1546 case PORT_SCIFA:
1526 return "scifa"; 1547 return "scifa";
1548 case PORT_SCIFB:
1549 return "scifb";
1527 } 1550 }
1528 1551
1529 return NULL; 1552 return NULL;
@@ -1612,6 +1635,9 @@ static int __devinit sci_init_single(struct platform_device *dev,
1612 port->line = index; 1635 port->line = index;
1613 1636
1614 switch (p->type) { 1637 switch (p->type) {
1638 case PORT_SCIFB:
1639 port->fifosize = 256;
1640 break;
1615 case PORT_SCIFA: 1641 case PORT_SCIFA:
1616 port->fifosize = 64; 1642 port->fifosize = 64;
1617 break; 1643 break;
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index f70c49f915f..9b52f77a930 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -322,7 +322,7 @@
322#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ 322#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
323 static inline unsigned int sci_##name##_in(struct uart_port *port) \ 323 static inline unsigned int sci_##name##_in(struct uart_port *port) \
324 { \ 324 { \
325 if (port->type == PORT_SCIF) { \ 325 if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \
326 SCI_IN(scif_size, scif_offset) \ 326 SCI_IN(scif_size, scif_offset) \
327 } else { /* PORT_SCI or PORT_SCIFA */ \ 327 } else { /* PORT_SCI or PORT_SCIFA */ \
328 SCI_IN(sci_size, sci_offset); \ 328 SCI_IN(sci_size, sci_offset); \
@@ -330,7 +330,7 @@
330 } \ 330 } \
331 static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ 331 static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
332 { \ 332 { \
333 if (port->type == PORT_SCIF) { \ 333 if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \
334 SCI_OUT(scif_size, scif_offset, value) \ 334 SCI_OUT(scif_size, scif_offset, value) \
335 } else { /* PORT_SCI or PORT_SCIFA */ \ 335 } else { /* PORT_SCI or PORT_SCIFA */ \
336 SCI_OUT(sci_size, sci_offset, value); \ 336 SCI_OUT(sci_size, sci_offset, value); \
@@ -384,8 +384,12 @@
384 defined(CONFIG_CPU_SUBTYPE_SH7720) || \ 384 defined(CONFIG_CPU_SUBTYPE_SH7720) || \
385 defined(CONFIG_CPU_SUBTYPE_SH7721) || \ 385 defined(CONFIG_CPU_SUBTYPE_SH7721) || \
386 defined(CONFIG_ARCH_SH7367) || \ 386 defined(CONFIG_ARCH_SH7367) || \
387 defined(CONFIG_ARCH_SH7377) || \ 387 defined(CONFIG_ARCH_SH7377)
388 defined(CONFIG_ARCH_SH7372) 388#define SCIF_FNS(name, scif_offset, scif_size) \
389 CPU_SCIF_FNS(name, scif_offset, scif_size)
390#elif defined(CONFIG_ARCH_SH7372)
391#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \
392 CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size)
389#define SCIF_FNS(name, scif_offset, scif_size) \ 393#define SCIF_FNS(name, scif_offset, scif_size) \
390 CPU_SCIF_FNS(name, scif_offset, scif_size) 394 CPU_SCIF_FNS(name, scif_offset, scif_size)
391#else 395#else
@@ -422,8 +426,7 @@
422 defined(CONFIG_CPU_SUBTYPE_SH7720) || \ 426 defined(CONFIG_CPU_SUBTYPE_SH7720) || \
423 defined(CONFIG_CPU_SUBTYPE_SH7721) || \ 427 defined(CONFIG_CPU_SUBTYPE_SH7721) || \
424 defined(CONFIG_ARCH_SH7367) || \ 428 defined(CONFIG_ARCH_SH7367) || \
425 defined(CONFIG_ARCH_SH7377) || \ 429 defined(CONFIG_ARCH_SH7377)
426 defined(CONFIG_ARCH_SH7372)
427 430
428SCIF_FNS(SCSMR, 0x00, 16) 431SCIF_FNS(SCSMR, 0x00, 16)
429SCIF_FNS(SCBRR, 0x04, 8) 432SCIF_FNS(SCBRR, 0x04, 8)
@@ -436,6 +439,20 @@ SCIF_FNS(SCFDR, 0x1c, 16)
436SCIF_FNS(SCxTDR, 0x20, 8) 439SCIF_FNS(SCxTDR, 0x20, 8)
437SCIF_FNS(SCxRDR, 0x24, 8) 440SCIF_FNS(SCxRDR, 0x24, 8)
438SCIF_FNS(SCLSR, 0x00, 0) 441SCIF_FNS(SCLSR, 0x00, 0)
442#elif defined(CONFIG_ARCH_SH7372)
443SCIF_FNS(SCSMR, 0x00, 16)
444SCIF_FNS(SCBRR, 0x04, 8)
445SCIF_FNS(SCSCR, 0x08, 16)
446SCIF_FNS(SCTDSR, 0x0c, 16)
447SCIF_FNS(SCFER, 0x10, 16)
448SCIF_FNS(SCxSR, 0x14, 16)
449SCIF_FNS(SCFCR, 0x18, 16)
450SCIF_FNS(SCFDR, 0x1c, 16)
451SCIF_FNS(SCTFDR, 0x38, 16)
452SCIF_FNS(SCRFDR, 0x3c, 16)
453SCIx_FNS(SCxTDR, 0x20, 8, 0x40, 8)
454SCIx_FNS(SCxRDR, 0x24, 8, 0x60, 8)
455SCIF_FNS(SCLSR, 0x00, 0)
439#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ 456#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
440 defined(CONFIG_CPU_SUBTYPE_SH7724) 457 defined(CONFIG_CPU_SUBTYPE_SH7724)
441SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) 458SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16)
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile
index 78bb5127abd..08fc653a825 100644
--- a/drivers/sh/Makefile
+++ b/drivers/sh/Makefile
@@ -1,9 +1,10 @@
1# 1#
2# Makefile for the SuperH specific drivers. 2# Makefile for the SuperH specific drivers.
3# 3#
4obj-y := clk.o intc.o
5
4obj-$(CONFIG_SUPERHYWAY) += superhyway/ 6obj-$(CONFIG_SUPERHYWAY) += superhyway/
5obj-$(CONFIG_MAPLE) += maple/ 7obj-$(CONFIG_MAPLE) += maple/
8
6obj-$(CONFIG_GENERIC_GPIO) += pfc.o 9obj-$(CONFIG_GENERIC_GPIO) += pfc.o
7obj-$(CONFIG_SUPERH) += clk.o
8obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o 10obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o
9obj-y += intc.o
diff --git a/drivers/sh/clk-cpg.c b/drivers/sh/clk-cpg.c
index f5c80ba9ab1..8c024b984ed 100644
--- a/drivers/sh/clk-cpg.c
+++ b/drivers/sh/clk-cpg.c
@@ -68,6 +68,39 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
68 return clk->freq_table[idx].frequency; 68 return clk->freq_table[idx].frequency;
69} 69}
70 70
71static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
72{
73 struct clk_div_mult_table *table = &sh_clk_div6_table;
74 u32 value;
75 int ret, i;
76
77 if (!clk->parent_table || !clk->parent_num)
78 return -EINVAL;
79
80 /* Search the parent */
81 for (i = 0; i < clk->parent_num; i++)
82 if (clk->parent_table[i] == parent)
83 break;
84
85 if (i == clk->parent_num)
86 return -ENODEV;
87
88 ret = clk_reparent(clk, parent);
89 if (ret < 0)
90 return ret;
91
92 value = __raw_readl(clk->enable_reg) &
93 ~(((1 << clk->src_width) - 1) << clk->src_shift);
94
95 __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
96
97 /* Rebuild the frequency table */
98 clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
99 table, &clk->arch_flags);
100
101 return 0;
102}
103
71static int sh_clk_div6_set_rate(struct clk *clk, 104static int sh_clk_div6_set_rate(struct clk *clk,
72 unsigned long rate, int algo_id) 105 unsigned long rate, int algo_id)
73{ 106{
@@ -117,7 +150,17 @@ static struct clk_ops sh_clk_div6_clk_ops = {
117 .disable = sh_clk_div6_disable, 150 .disable = sh_clk_div6_disable,
118}; 151};
119 152
120int __init sh_clk_div6_register(struct clk *clks, int nr) 153static struct clk_ops sh_clk_div6_reparent_clk_ops = {
154 .recalc = sh_clk_div6_recalc,
155 .round_rate = sh_clk_div_round_rate,
156 .set_rate = sh_clk_div6_set_rate,
157 .enable = sh_clk_div6_enable,
158 .disable = sh_clk_div6_disable,
159 .set_parent = sh_clk_div6_set_parent,
160};
161
162static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
163 struct clk_ops *ops)
121{ 164{
122 struct clk *clkp; 165 struct clk *clkp;
123 void *freq_table; 166 void *freq_table;
@@ -136,7 +179,7 @@ int __init sh_clk_div6_register(struct clk *clks, int nr)
136 for (k = 0; !ret && (k < nr); k++) { 179 for (k = 0; !ret && (k < nr); k++) {
137 clkp = clks + k; 180 clkp = clks + k;
138 181
139 clkp->ops = &sh_clk_div6_clk_ops; 182 clkp->ops = ops;
140 clkp->id = -1; 183 clkp->id = -1;
141 clkp->freq_table = freq_table + (k * freq_table_size); 184 clkp->freq_table = freq_table + (k * freq_table_size);
142 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; 185 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
@@ -147,6 +190,17 @@ int __init sh_clk_div6_register(struct clk *clks, int nr)
147 return ret; 190 return ret;
148} 191}
149 192
193int __init sh_clk_div6_register(struct clk *clks, int nr)
194{
195 return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops);
196}
197
198int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
199{
200 return sh_clk_div6_register_ops(clks, nr,
201 &sh_clk_div6_reparent_clk_ops);
202}
203
150static unsigned long sh_clk_div4_recalc(struct clk *clk) 204static unsigned long sh_clk_div4_recalc(struct clk *clk)
151{ 205{
152 struct clk_div4_table *d4t = clk->priv; 206 struct clk_div4_table *d4t = clk->priv;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 7b11ea68c80..bbeee4ba248 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1896,6 +1896,13 @@ config FB_W100
1896 1896
1897 If unsure, say N. 1897 If unsure, say N.
1898 1898
1899config SH_MIPI_DSI
1900 tristate
1901 depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
1902
1903config SH_LCD_MIPI_DSI
1904 bool
1905
1899config FB_SH_MOBILE_LCDC 1906config FB_SH_MOBILE_LCDC
1900 tristate "SuperH Mobile LCDC framebuffer support" 1907 tristate "SuperH Mobile LCDC framebuffer support"
1901 depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK 1908 depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
@@ -1904,9 +1911,17 @@ config FB_SH_MOBILE_LCDC
1904 select FB_SYS_IMAGEBLIT 1911 select FB_SYS_IMAGEBLIT
1905 select FB_SYS_FOPS 1912 select FB_SYS_FOPS
1906 select FB_DEFERRED_IO 1913 select FB_DEFERRED_IO
1914 select SH_MIPI_DSI if SH_LCD_MIPI_DSI
1907 ---help--- 1915 ---help---
1908 Frame buffer driver for the on-chip SH-Mobile LCD controller. 1916 Frame buffer driver for the on-chip SH-Mobile LCD controller.
1909 1917
1918config FB_SH_MOBILE_HDMI
1919 tristate "SuperH Mobile HDMI controller support"
1920 depends on FB_SH_MOBILE_LCDC
1921 select FB_MODE_HELPERS
1922 ---help---
1923 Driver for the on-chip SH-Mobile HDMI controller.
1924
1910config FB_TMIO 1925config FB_TMIO
1911 tristate "Toshiba Mobile IO FrameBuffer support" 1926 tristate "Toshiba Mobile IO FrameBuffer support"
1912 depends on FB && MFD_CORE 1927 depends on FB && MFD_CORE
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index f56a9cae215..485e8ed1318 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -123,6 +123,8 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
123obj-$(CONFIG_FB_PS3) += ps3fb.o 123obj-$(CONFIG_FB_PS3) += ps3fb.o
124obj-$(CONFIG_FB_SM501) += sm501fb.o 124obj-$(CONFIG_FB_SM501) += sm501fb.o
125obj-$(CONFIG_FB_XILINX) += xilinxfb.o 125obj-$(CONFIG_FB_XILINX) += xilinxfb.o
126obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
127obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
126obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o 128obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
127obj-$(CONFIG_FB_OMAP) += omap/ 129obj-$(CONFIG_FB_OMAP) += omap/
128obj-y += omap2/ 130obj-y += omap2/
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
new file mode 100644
index 00000000000..5699ce0c178
--- /dev/null
+++ b/drivers/video/sh_mipi_dsi.c
@@ -0,0 +1,505 @@
1/*
2 * Renesas SH-mobile MIPI DSI support
3 *
4 * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 *
6 * This is free software; you can redistribute it and/or modify
7 * it under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/clk.h>
12#include <linux/delay.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <linux/string.h>
18#include <linux/types.h>
19
20#include <video/mipi_display.h>
21#include <video/sh_mipi_dsi.h>
22#include <video/sh_mobile_lcdc.h>
23
24#define CMTSRTCTR 0x80d0
25#define CMTSRTREQ 0x8070
26
27#define DSIINTE 0x0060
28
29/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */
30#define MAX_SH_MIPI_DSI 2
31
32struct sh_mipi {
33 void __iomem *base;
34 struct clk *dsit_clk;
35 struct clk *dsip_clk;
36};
37
38static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
39
40/* Protect the above array */
41static DEFINE_MUTEX(array_lock);
42
43static struct sh_mipi *sh_mipi_by_handle(int handle)
44{
45 if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0)
46 return NULL;
47
48 return mipi_dsi[handle];
49}
50
51static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd,
52 u8 cmd, u8 param)
53{
54 u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8);
55 int cnt = 100;
56
57 /* transmit a short packet to LCD panel */
58 iowrite32(1 | data, mipi->base + 0x80d0); /* CMTSRTCTR */
59 iowrite32(1, mipi->base + 0x8070); /* CMTSRTREQ */
60
61 while ((ioread32(mipi->base + 0x8070) & 1) && --cnt)
62 udelay(1);
63
64 return cnt ? 0 : -ETIMEDOUT;
65}
66
67#define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \
68 -EINVAL : (c) - 1)
69
70static int sh_mipi_dcs(int handle, u8 cmd)
71{
72 struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
73 if (!mipi)
74 return -ENODEV;
75 return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0);
76}
77
78static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param)
79{
80 struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
81 if (!mipi)
82 return -ENODEV;
83 return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd,
84 param);
85}
86
87static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
88{
89 /*
90 * enable LCDC data tx, transition to LPS after completion of each HS
91 * packet
92 */
93 iowrite32(0x00000002 | enable, mipi->base + 0x8000); /* DTCTR */
94}
95
96static void sh_mipi_shutdown(struct platform_device *pdev)
97{
98 struct sh_mipi *mipi = platform_get_drvdata(pdev);
99
100 sh_mipi_dsi_enable(mipi, false);
101}
102
103static void mipi_display_on(void *arg, struct fb_info *info)
104{
105 struct sh_mipi *mipi = arg;
106
107 sh_mipi_dsi_enable(mipi, true);
108}
109
110static void mipi_display_off(void *arg)
111{
112 struct sh_mipi *mipi = arg;
113
114 sh_mipi_dsi_enable(mipi, false);
115}
116
117static int __init sh_mipi_setup(struct sh_mipi *mipi,
118 struct sh_mipi_dsi_info *pdata)
119{
120 void __iomem *base = mipi->base;
121 struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
122 u32 pctype, datatype, pixfmt;
123 u32 linelength;
124 bool yuv;
125
126 /* Select data format */
127 switch (pdata->data_format) {
128 case MIPI_RGB888:
129 pctype = 0;
130 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
131 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
132 linelength = ch->lcd_cfg.xres * 3;
133 yuv = false;
134 break;
135 case MIPI_RGB565:
136 pctype = 1;
137 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
138 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
139 linelength = ch->lcd_cfg.xres * 2;
140 yuv = false;
141 break;
142 case MIPI_RGB666_LP:
143 pctype = 2;
144 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
145 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
146 linelength = ch->lcd_cfg.xres * 3;
147 yuv = false;
148 break;
149 case MIPI_RGB666:
150 pctype = 3;
151 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
152 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
153 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8;
154 yuv = false;
155 break;
156 case MIPI_BGR888:
157 pctype = 8;
158 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
159 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
160 linelength = ch->lcd_cfg.xres * 3;
161 yuv = false;
162 break;
163 case MIPI_BGR565:
164 pctype = 9;
165 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
166 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
167 linelength = ch->lcd_cfg.xres * 2;
168 yuv = false;
169 break;
170 case MIPI_BGR666_LP:
171 pctype = 0xa;
172 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
173 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
174 linelength = ch->lcd_cfg.xres * 3;
175 yuv = false;
176 break;
177 case MIPI_BGR666:
178 pctype = 0xb;
179 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
180 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
181 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8;
182 yuv = false;
183 break;
184 case MIPI_YUYV:
185 pctype = 4;
186 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
187 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
188 linelength = ch->lcd_cfg.xres * 2;
189 yuv = true;
190 break;
191 case MIPI_UYVY:
192 pctype = 5;
193 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
194 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
195 linelength = ch->lcd_cfg.xres * 2;
196 yuv = true;
197 break;
198 case MIPI_YUV420_L:
199 pctype = 6;
200 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
201 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
202 linelength = (ch->lcd_cfg.xres * 12 + 7) / 8;
203 yuv = true;
204 break;
205 case MIPI_YUV420:
206 pctype = 7;
207 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
208 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
209 /* Length of U/V line */
210 linelength = (ch->lcd_cfg.xres + 1) / 2;
211 yuv = true;
212 break;
213 default:
214 return -EINVAL;
215 }
216
217 if ((yuv && ch->interface_type != YUV422) ||
218 (!yuv && ch->interface_type != RGB24))
219 return -EINVAL;
220
221 /* reset DSI link */
222 iowrite32(0x00000001, base); /* SYSCTRL */
223 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
224 udelay(50);
225 iowrite32(0x00000000, base); /* SYSCTRL */
226
227 /* setup DSI link */
228
229 /*
230 * Default = ULPS enable |
231 * Contention detection enabled |
232 * EoT packet transmission enable |
233 * CRC check enable |
234 * ECC check enable
235 * additionally enable first two lanes
236 */
237 iowrite32(0x00003703, base + 0x04); /* SYSCONF */
238 /*
239 * T_wakeup = 0x7000
240 * T_hs-trail = 3
241 * T_hs-prepare = 3
242 * T_clk-trail = 3
243 * T_clk-prepare = 2
244 */
245 iowrite32(0x70003332, base + 0x08); /* TIMSET */
246 /* no responses requested */
247 iowrite32(0x00000000, base + 0x18); /* RESREQSET0 */
248 /* request response to packets of type 0x28 */
249 iowrite32(0x00000100, base + 0x1c); /* RESREQSET1 */
250 /* High-speed transmission timeout, default 0xffffffff */
251 iowrite32(0x0fffffff, base + 0x20); /* HSTTOVSET */
252 /* LP reception timeout, default 0xffffffff */
253 iowrite32(0x0fffffff, base + 0x24); /* LPRTOVSET */
254 /* Turn-around timeout, default 0xffffffff */
255 iowrite32(0x0fffffff, base + 0x28); /* TATOVSET */
256 /* Peripheral reset timeout, default 0xffffffff */
257 iowrite32(0x0fffffff, base + 0x2c); /* PRTOVSET */
258 /* Enable timeout counters */
259 iowrite32(0x00000f00, base + 0x30); /* DSICTRL */
260 /* Interrupts not used, disable all */
261 iowrite32(0, base + DSIINTE);
262 /* DSI-Tx bias on */
263 iowrite32(0x00000001, base + 0x70); /* PHYCTRL */
264 udelay(200);
265 /* Deassert resets, power on, set multiplier */
266 iowrite32(0x03070b01, base + 0x70); /* PHYCTRL */
267
268 /* setup l-bridge */
269
270 /*
271 * Enable transmission of all packets,
272 * transmit LPS after each HS packet completion
273 */
274 iowrite32(0x00000006, base + 0x8000); /* DTCTR */
275 /* VSYNC width = 2 (<< 17) */
276 iowrite32(0x00040000 | (pctype << 12) | datatype, base + 0x8020); /* VMCTR1 */
277 /*
278 * Non-burst mode with sync pulses: VSE and HSE are output,
279 * HSA period allowed, no commands in LP
280 */
281 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */
282 /*
283 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
284 * sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default
285 * (unused, since VMCTR2[HSABM] = 0)
286 */
287 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */
288
289 msleep(5);
290
291 /* setup LCD panel */
292
293 /* cf. drivers/video/omap/lcd_mipid.c */
294 sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE);
295 msleep(120);
296 /*
297 * [7] - Page Address Mode
298 * [6] - Column Address Mode
299 * [5] - Page / Column Address Mode
300 * [4] - Display Device Line Refresh Order
301 * [3] - RGB/BGR Order
302 * [2] - Display Data Latch Data Order
303 * [1] - Flip Horizontal
304 * [0] - Flip Vertical
305 */
306 sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
307 /* cf. set_data_lines() */
308 sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT,
309 pixfmt << 4);
310 sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
311
312 return 0;
313}
314
315static int __init sh_mipi_probe(struct platform_device *pdev)
316{
317 struct sh_mipi *mipi;
318 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
319 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
320 unsigned long rate, f_current;
321 int idx = pdev->id, ret;
322 char dsip_clk[] = "dsi.p_clk";
323
324 if (!res || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
325 return -ENODEV;
326
327 mutex_lock(&array_lock);
328 if (idx < 0)
329 for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
330 ;
331
332 if (idx == ARRAY_SIZE(mipi_dsi)) {
333 ret = -EBUSY;
334 goto efindslot;
335 }
336
337 mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
338 if (!mipi) {
339 ret = -ENOMEM;
340 goto ealloc;
341 }
342
343 if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
344 dev_err(&pdev->dev, "MIPI register region already claimed\n");
345 ret = -EBUSY;
346 goto ereqreg;
347 }
348
349 mipi->base = ioremap(res->start, resource_size(res));
350 if (!mipi->base) {
351 ret = -ENOMEM;
352 goto emap;
353 }
354
355 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
356 if (IS_ERR(mipi->dsit_clk)) {
357 ret = PTR_ERR(mipi->dsit_clk);
358 goto eclktget;
359 }
360
361 f_current = clk_get_rate(mipi->dsit_clk);
362 /* 80MHz required by the datasheet */
363 rate = clk_round_rate(mipi->dsit_clk, 80000000);
364 if (rate > 0 && rate != f_current)
365 ret = clk_set_rate(mipi->dsit_clk, rate);
366 else
367 ret = rate;
368 if (ret < 0)
369 goto esettrate;
370
371 dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
372
373 sprintf(dsip_clk, "dsi%1.1dp_clk", idx);
374 mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk);
375 if (IS_ERR(mipi->dsip_clk)) {
376 ret = PTR_ERR(mipi->dsip_clk);
377 goto eclkpget;
378 }
379
380 f_current = clk_get_rate(mipi->dsip_clk);
381 /* Between 10 and 50MHz */
382 rate = clk_round_rate(mipi->dsip_clk, 24000000);
383 if (rate > 0 && rate != f_current)
384 ret = clk_set_rate(mipi->dsip_clk, rate);
385 else
386 ret = rate;
387 if (ret < 0)
388 goto esetprate;
389
390 dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate);
391
392 msleep(10);
393
394 ret = clk_enable(mipi->dsit_clk);
395 if (ret < 0)
396 goto eclkton;
397
398 ret = clk_enable(mipi->dsip_clk);
399 if (ret < 0)
400 goto eclkpon;
401
402 mipi_dsi[idx] = mipi;
403
404 ret = sh_mipi_setup(mipi, pdata);
405 if (ret < 0)
406 goto emipisetup;
407
408 mutex_unlock(&array_lock);
409 platform_set_drvdata(pdev, mipi);
410
411 /* Set up LCDC callbacks */
412 pdata->lcd_chan->board_cfg.board_data = mipi;
413 pdata->lcd_chan->board_cfg.display_on = mipi_display_on;
414 pdata->lcd_chan->board_cfg.display_off = mipi_display_off;
415
416 return 0;
417
418emipisetup:
419 mipi_dsi[idx] = NULL;
420 clk_disable(mipi->dsip_clk);
421eclkpon:
422 clk_disable(mipi->dsit_clk);
423eclkton:
424esetprate:
425 clk_put(mipi->dsip_clk);
426eclkpget:
427esettrate:
428 clk_put(mipi->dsit_clk);
429eclktget:
430 iounmap(mipi->base);
431emap:
432 release_mem_region(res->start, resource_size(res));
433ereqreg:
434 kfree(mipi);
435ealloc:
436efindslot:
437 mutex_unlock(&array_lock);
438
439 return ret;
440}
441
442static int __exit sh_mipi_remove(struct platform_device *pdev)
443{
444 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
445 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
446 struct sh_mipi *mipi = platform_get_drvdata(pdev);
447 int i, ret;
448
449 mutex_lock(&array_lock);
450
451 for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++)
452 ;
453
454 if (i == ARRAY_SIZE(mipi_dsi)) {
455 ret = -EINVAL;
456 } else {
457 ret = 0;
458 mipi_dsi[i] = NULL;
459 }
460
461 mutex_unlock(&array_lock);
462
463 if (ret < 0)
464 return ret;
465
466 pdata->lcd_chan->board_cfg.display_on = NULL;
467 pdata->lcd_chan->board_cfg.display_off = NULL;
468 pdata->lcd_chan->board_cfg.board_data = NULL;
469
470 clk_disable(mipi->dsip_clk);
471 clk_disable(mipi->dsit_clk);
472 clk_put(mipi->dsit_clk);
473 clk_put(mipi->dsip_clk);
474 iounmap(mipi->base);
475 if (res)
476 release_mem_region(res->start, resource_size(res));
477 platform_set_drvdata(pdev, NULL);
478 kfree(mipi);
479
480 return 0;
481}
482
483static struct platform_driver sh_mipi_driver = {
484 .remove = __exit_p(sh_mipi_remove),
485 .shutdown = sh_mipi_shutdown,
486 .driver = {
487 .name = "sh-mipi-dsi",
488 },
489};
490
491static int __init sh_mipi_init(void)
492{
493 return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe);
494}
495module_init(sh_mipi_init);
496
497static void __exit sh_mipi_exit(void)
498{
499 platform_driver_unregister(&sh_mipi_driver);
500}
501module_exit(sh_mipi_exit);
502
503MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
504MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
505MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
new file mode 100644
index 00000000000..2fde08cc66b
--- /dev/null
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -0,0 +1,1028 @@
1/*
2 * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
3 * for SLISHDMI13T and SLIPHDMIT IP cores
4 *
5 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/clk.h>
13#include <linux/console.h>
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/init.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/pm_runtime.h>
22#include <linux/slab.h>
23#include <linux/types.h>
24#include <linux/workqueue.h>
25
26#include <video/sh_mobile_hdmi.h>
27#include <video/sh_mobile_lcdc.h>
28
29#define HDMI_SYSTEM_CTRL 0x00 /* System control */
30#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control,
31 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
32#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8 0x02 /* bits 15..8 of 20-bit N for Audio Clock Regeneration packet */
33#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0 0x03 /* bits 7..0 of 20-bit N for Audio Clock Regeneration packet */
34#define HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS 0x04 /* SPDIF audio sampling frequency,
35 bits 19..16 of Internal CTS */
36#define HDMI_INTERNAL_CTS_15_8 0x05 /* bits 15..8 of Internal CTS */
37#define HDMI_INTERNAL_CTS_7_0 0x06 /* bits 7..0 of Internal CTS */
38#define HDMI_EXTERNAL_CTS_19_16 0x07 /* External CTS */
39#define HDMI_EXTERNAL_CTS_15_8 0x08 /* External CTS */
40#define HDMI_EXTERNAL_CTS_7_0 0x09 /* External CTS */
41#define HDMI_AUDIO_SETTING_1 0x0A /* Audio setting.1 */
42#define HDMI_AUDIO_SETTING_2 0x0B /* Audio setting.2 */
43#define HDMI_I2S_AUDIO_SET 0x0C /* I2S audio setting */
44#define HDMI_DSD_AUDIO_SET 0x0D /* DSD audio setting */
45#define HDMI_DEBUG_MONITOR_1 0x0E /* Debug monitor.1 */
46#define HDMI_DEBUG_MONITOR_2 0x0F /* Debug monitor.2 */
47#define HDMI_I2S_INPUT_PIN_SWAP 0x10 /* I2S input pin swap */
48#define HDMI_AUDIO_STATUS_BITS_SETTING_1 0x11 /* Audio status bits setting.1 */
49#define HDMI_AUDIO_STATUS_BITS_SETTING_2 0x12 /* Audio status bits setting.2 */
50#define HDMI_CATEGORY_CODE 0x13 /* Category code */
51#define HDMI_SOURCE_NUM_AUDIO_WORD_LEN 0x14 /* Source number/Audio word length */
52#define HDMI_AUDIO_VIDEO_SETTING_1 0x15 /* Audio/Video setting.1 */
53#define HDMI_VIDEO_SETTING_1 0x16 /* Video setting.1 */
54#define HDMI_DEEP_COLOR_MODES 0x17 /* Deep Color Modes */
55
56/* 12 16- and 10-bit Color space conversion parameters: 0x18..0x2f */
57#define HDMI_COLOR_SPACE_CONVERSION_PARAMETERS 0x18
58
59#define HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS 0x30 /* External video parameter settings */
60#define HDMI_EXTERNAL_H_TOTAL_7_0 0x31 /* External horizontal total (LSB) */
61#define HDMI_EXTERNAL_H_TOTAL_11_8 0x32 /* External horizontal total (MSB) */
62#define HDMI_EXTERNAL_H_BLANK_7_0 0x33 /* External horizontal blank (LSB) */
63#define HDMI_EXTERNAL_H_BLANK_9_8 0x34 /* External horizontal blank (MSB) */
64#define HDMI_EXTERNAL_H_DELAY_7_0 0x35 /* External horizontal delay (LSB) */
65#define HDMI_EXTERNAL_H_DELAY_9_8 0x36 /* External horizontal delay (MSB) */
66#define HDMI_EXTERNAL_H_DURATION_7_0 0x37 /* External horizontal duration (LSB) */
67#define HDMI_EXTERNAL_H_DURATION_9_8 0x38 /* External horizontal duration (MSB) */
68#define HDMI_EXTERNAL_V_TOTAL_7_0 0x39 /* External vertical total (LSB) */
69#define HDMI_EXTERNAL_V_TOTAL_9_8 0x3A /* External vertical total (MSB) */
70#define HDMI_AUDIO_VIDEO_SETTING_2 0x3B /* Audio/Video setting.2 */
71#define HDMI_EXTERNAL_V_BLANK 0x3D /* External vertical blank */
72#define HDMI_EXTERNAL_V_DELAY 0x3E /* External vertical delay */
73#define HDMI_EXTERNAL_V_DURATION 0x3F /* External vertical duration */
74#define HDMI_CTRL_PKT_MANUAL_SEND_CONTROL 0x40 /* Control packet manual send control */
75#define HDMI_CTRL_PKT_AUTO_SEND 0x41 /* Control packet auto send with VSYNC control */
76#define HDMI_AUTO_CHECKSUM_OPTION 0x42 /* Auto checksum option */
77#define HDMI_VIDEO_SETTING_2 0x45 /* Video setting.2 */
78#define HDMI_OUTPUT_OPTION 0x46 /* Output option */
79#define HDMI_SLIPHDMIT_PARAM_OPTION 0x51 /* SLIPHDMIT parameter option */
80#define HDMI_HSYNC_PMENT_AT_EMB_7_0 0x52 /* HSYNC placement at embedded sync (LSB) */
81#define HDMI_HSYNC_PMENT_AT_EMB_15_8 0x53 /* HSYNC placement at embedded sync (MSB) */
82#define HDMI_VSYNC_PMENT_AT_EMB_7_0 0x54 /* VSYNC placement at embedded sync (LSB) */
83#define HDMI_VSYNC_PMENT_AT_EMB_14_8 0x55 /* VSYNC placement at embedded sync (MSB) */
84#define HDMI_SLIPHDMIT_PARAM_SETTINGS_1 0x56 /* SLIPHDMIT parameter settings.1 */
85#define HDMI_SLIPHDMIT_PARAM_SETTINGS_2 0x57 /* SLIPHDMIT parameter settings.2 */
86#define HDMI_SLIPHDMIT_PARAM_SETTINGS_3 0x58 /* SLIPHDMIT parameter settings.3 */
87#define HDMI_SLIPHDMIT_PARAM_SETTINGS_5 0x59 /* SLIPHDMIT parameter settings.5 */
88#define HDMI_SLIPHDMIT_PARAM_SETTINGS_6 0x5A /* SLIPHDMIT parameter settings.6 */
89#define HDMI_SLIPHDMIT_PARAM_SETTINGS_7 0x5B /* SLIPHDMIT parameter settings.7 */
90#define HDMI_SLIPHDMIT_PARAM_SETTINGS_8 0x5C /* SLIPHDMIT parameter settings.8 */
91#define HDMI_SLIPHDMIT_PARAM_SETTINGS_9 0x5D /* SLIPHDMIT parameter settings.9 */
92#define HDMI_SLIPHDMIT_PARAM_SETTINGS_10 0x5E /* SLIPHDMIT parameter settings.10 */
93#define HDMI_CTRL_PKT_BUF_INDEX 0x5F /* Control packet buffer index */
94#define HDMI_CTRL_PKT_BUF_ACCESS_HB0 0x60 /* Control packet data buffer access window - HB0 */
95#define HDMI_CTRL_PKT_BUF_ACCESS_HB1 0x61 /* Control packet data buffer access window - HB1 */
96#define HDMI_CTRL_PKT_BUF_ACCESS_HB2 0x62 /* Control packet data buffer access window - HB2 */
97#define HDMI_CTRL_PKT_BUF_ACCESS_PB0 0x63 /* Control packet data buffer access window - PB0 */
98#define HDMI_CTRL_PKT_BUF_ACCESS_PB1 0x64 /* Control packet data buffer access window - PB1 */
99#define HDMI_CTRL_PKT_BUF_ACCESS_PB2 0x65 /* Control packet data buffer access window - PB2 */
100#define HDMI_CTRL_PKT_BUF_ACCESS_PB3 0x66 /* Control packet data buffer access window - PB3 */
101#define HDMI_CTRL_PKT_BUF_ACCESS_PB4 0x67 /* Control packet data buffer access window - PB4 */
102#define HDMI_CTRL_PKT_BUF_ACCESS_PB5 0x68 /* Control packet data buffer access window - PB5 */
103#define HDMI_CTRL_PKT_BUF_ACCESS_PB6 0x69 /* Control packet data buffer access window - PB6 */
104#define HDMI_CTRL_PKT_BUF_ACCESS_PB7 0x6A /* Control packet data buffer access window - PB7 */
105#define HDMI_CTRL_PKT_BUF_ACCESS_PB8 0x6B /* Control packet data buffer access window - PB8 */
106#define HDMI_CTRL_PKT_BUF_ACCESS_PB9 0x6C /* Control packet data buffer access window - PB9 */
107#define HDMI_CTRL_PKT_BUF_ACCESS_PB10 0x6D /* Control packet data buffer access window - PB10 */
108#define HDMI_CTRL_PKT_BUF_ACCESS_PB11 0x6E /* Control packet data buffer access window - PB11 */
109#define HDMI_CTRL_PKT_BUF_ACCESS_PB12 0x6F /* Control packet data buffer access window - PB12 */
110#define HDMI_CTRL_PKT_BUF_ACCESS_PB13 0x70 /* Control packet data buffer access window - PB13 */
111#define HDMI_CTRL_PKT_BUF_ACCESS_PB14 0x71 /* Control packet data buffer access window - PB14 */
112#define HDMI_CTRL_PKT_BUF_ACCESS_PB15 0x72 /* Control packet data buffer access window - PB15 */
113#define HDMI_CTRL_PKT_BUF_ACCESS_PB16 0x73 /* Control packet data buffer access window - PB16 */
114#define HDMI_CTRL_PKT_BUF_ACCESS_PB17 0x74 /* Control packet data buffer access window - PB17 */
115#define HDMI_CTRL_PKT_BUF_ACCESS_PB18 0x75 /* Control packet data buffer access window - PB18 */
116#define HDMI_CTRL_PKT_BUF_ACCESS_PB19 0x76 /* Control packet data buffer access window - PB19 */
117#define HDMI_CTRL_PKT_BUF_ACCESS_PB20 0x77 /* Control packet data buffer access window - PB20 */
118#define HDMI_CTRL_PKT_BUF_ACCESS_PB21 0x78 /* Control packet data buffer access window - PB21 */
119#define HDMI_CTRL_PKT_BUF_ACCESS_PB22 0x79 /* Control packet data buffer access window - PB22 */
120#define HDMI_CTRL_PKT_BUF_ACCESS_PB23 0x7A /* Control packet data buffer access window - PB23 */
121#define HDMI_CTRL_PKT_BUF_ACCESS_PB24 0x7B /* Control packet data buffer access window - PB24 */
122#define HDMI_CTRL_PKT_BUF_ACCESS_PB25 0x7C /* Control packet data buffer access window - PB25 */
123#define HDMI_CTRL_PKT_BUF_ACCESS_PB26 0x7D /* Control packet data buffer access window - PB26 */
124#define HDMI_CTRL_PKT_BUF_ACCESS_PB27 0x7E /* Control packet data buffer access window - PB27 */
125#define HDMI_EDID_KSV_FIFO_ACCESS_WINDOW 0x80 /* EDID/KSV FIFO access window */
126#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_7_0 0x81 /* DDC bus access frequency control (LSB) */
127#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_15_8 0x82 /* DDC bus access frequency control (MSB) */
128#define HDMI_INTERRUPT_MASK_1 0x92 /* Interrupt mask.1 */
129#define HDMI_INTERRUPT_MASK_2 0x93 /* Interrupt mask.2 */
130#define HDMI_INTERRUPT_STATUS_1 0x94 /* Interrupt status.1 */
131#define HDMI_INTERRUPT_STATUS_2 0x95 /* Interrupt status.2 */
132#define HDMI_INTERRUPT_MASK_3 0x96 /* Interrupt mask.3 */
133#define HDMI_INTERRUPT_MASK_4 0x97 /* Interrupt mask.4 */
134#define HDMI_INTERRUPT_STATUS_3 0x98 /* Interrupt status.3 */
135#define HDMI_INTERRUPT_STATUS_4 0x99 /* Interrupt status.4 */
136#define HDMI_SOFTWARE_HDCP_CONTROL_1 0x9A /* Software HDCP control.1 */
137#define HDMI_FRAME_COUNTER 0x9C /* Frame counter */
138#define HDMI_FRAME_COUNTER_FOR_RI_CHECK 0x9D /* Frame counter for Ri check */
139#define HDMI_HDCP_CONTROL 0xAF /* HDCP control */
140#define HDMI_RI_FRAME_COUNT_REGISTER 0xB2 /* Ri frame count register */
141#define HDMI_DDC_BUS_CONTROL 0xB7 /* DDC bus control */
142#define HDMI_HDCP_STATUS 0xB8 /* HDCP status */
143#define HDMI_SHA0 0xB9 /* sha0 */
144#define HDMI_SHA1 0xBA /* sha1 */
145#define HDMI_SHA2 0xBB /* sha2 */
146#define HDMI_SHA3 0xBC /* sha3 */
147#define HDMI_SHA4 0xBD /* sha4 */
148#define HDMI_BCAPS_READ 0xBE /* BCAPS read / debug */
149#define HDMI_AKSV_BKSV_7_0_MONITOR 0xBF /* AKSV/BKSV[7:0] monitor */
150#define HDMI_AKSV_BKSV_15_8_MONITOR 0xC0 /* AKSV/BKSV[15:8] monitor */
151#define HDMI_AKSV_BKSV_23_16_MONITOR 0xC1 /* AKSV/BKSV[23:16] monitor */
152#define HDMI_AKSV_BKSV_31_24_MONITOR 0xC2 /* AKSV/BKSV[31:24] monitor */
153#define HDMI_AKSV_BKSV_39_32_MONITOR 0xC3 /* AKSV/BKSV[39:32] monitor */
154#define HDMI_EDID_SEGMENT_POINTER 0xC4 /* EDID segment pointer */
155#define HDMI_EDID_WORD_ADDRESS 0xC5 /* EDID word address */
156#define HDMI_EDID_DATA_FIFO_ADDRESS 0xC6 /* EDID data FIFO address */
157#define HDMI_NUM_OF_HDMI_DEVICES 0xC7 /* Number of HDMI devices */
158#define HDMI_HDCP_ERROR_CODE 0xC8 /* HDCP error code */
159#define HDMI_100MS_TIMER_SET 0xC9 /* 100ms timer setting */
160#define HDMI_5SEC_TIMER_SET 0xCA /* 5sec timer setting */
161#define HDMI_RI_READ_COUNT 0xCB /* Ri read count */
162#define HDMI_AN_SEED 0xCC /* An seed */
163#define HDMI_MAX_NUM_OF_RCIVRS_ALLOWED 0xCD /* Maximum number of receivers allowed */
164#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_1 0xCE /* HDCP memory access control.1 */
165#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_2 0xCF /* HDCP memory access control.2 */
166#define HDMI_HDCP_CONTROL_2 0xD0 /* HDCP Control 2 */
167#define HDMI_HDCP_KEY_MEMORY_CONTROL 0xD2 /* HDCP Key Memory Control */
168#define HDMI_COLOR_SPACE_CONV_CONFIG_1 0xD3 /* Color space conversion configuration.1 */
169#define HDMI_VIDEO_SETTING_3 0xD4 /* Video setting.3 */
170#define HDMI_RI_7_0 0xD5 /* Ri[7:0] */
171#define HDMI_RI_15_8 0xD6 /* Ri[15:8] */
172#define HDMI_PJ 0xD7 /* Pj */
173#define HDMI_SHA_RD 0xD8 /* sha_rd */
174#define HDMI_RI_7_0_SAVED 0xD9 /* Ri[7:0] saved */
175#define HDMI_RI_15_8_SAVED 0xDA /* Ri[15:8] saved */
176#define HDMI_PJ_SAVED 0xDB /* Pj saved */
177#define HDMI_NUM_OF_DEVICES 0xDC /* Number of devices */
178#define HDMI_HOT_PLUG_MSENS_STATUS 0xDF /* Hot plug/MSENS status */
179#define HDMI_BCAPS_WRITE 0xE0 /* bcaps */
180#define HDMI_BSTAT_7_0 0xE1 /* bstat[7:0] */
181#define HDMI_BSTAT_15_8 0xE2 /* bstat[15:8] */
182#define HDMI_BKSV_7_0 0xE3 /* bksv[7:0] */
183#define HDMI_BKSV_15_8 0xE4 /* bksv[15:8] */
184#define HDMI_BKSV_23_16 0xE5 /* bksv[23:16] */
185#define HDMI_BKSV_31_24 0xE6 /* bksv[31:24] */
186#define HDMI_BKSV_39_32 0xE7 /* bksv[39:32] */
187#define HDMI_AN_7_0 0xE8 /* An[7:0] */
188#define HDMI_AN_15_8 0xE9 /* An [15:8] */
189#define HDMI_AN_23_16 0xEA /* An [23:16] */
190#define HDMI_AN_31_24 0xEB /* An [31:24] */
191#define HDMI_AN_39_32 0xEC /* An [39:32] */
192#define HDMI_AN_47_40 0xED /* An [47:40] */
193#define HDMI_AN_55_48 0xEE /* An [55:48] */
194#define HDMI_AN_63_56 0xEF /* An [63:56] */
195#define HDMI_PRODUCT_ID 0xF0 /* Product ID */
196#define HDMI_REVISION_ID 0xF1 /* Revision ID */
197#define HDMI_TEST_MODE 0xFE /* Test mode */
198
199enum hotplug_state {
200 HDMI_HOTPLUG_DISCONNECTED,
201 HDMI_HOTPLUG_CONNECTED,
202 HDMI_HOTPLUG_EDID_DONE,
203};
204
205struct sh_hdmi {
206 void __iomem *base;
207 enum hotplug_state hp_state;
208 struct clk *hdmi_clk;
209 struct device *dev;
210 struct fb_info *info;
211 struct delayed_work edid_work;
212 struct fb_var_screeninfo var;
213};
214
215static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
216{
217 iowrite8(data, hdmi->base + reg);
218}
219
220static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
221{
222 return ioread8(hdmi->base + reg);
223}
224
225/* External video parameter settings */
226static void hdmi_external_video_param(struct sh_hdmi *hdmi)
227{
228 struct fb_var_screeninfo *var = &hdmi->var;
229 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
230 u8 sync = 0;
231
232 htotal = var->xres + var->right_margin + var->left_margin + var->hsync_len;
233
234 hdelay = var->hsync_len + var->left_margin;
235 hblank = var->right_margin + hdelay;
236
237 /*
238 * Vertical timing looks a bit different in Figure 18,
239 * but let's try the same first by setting offset = 0
240 */
241 vtotal = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
242
243 vdelay = var->vsync_len + var->upper_margin;
244 vblank = var->lower_margin + vdelay;
245 voffset = min(var->upper_margin / 2, 6U);
246
247 /*
248 * [3]: VSYNC polarity: Positive
249 * [2]: HSYNC polarity: Positive
250 * [1]: Interlace/Progressive: Progressive
251 * [0]: External video settings enable: used.
252 */
253 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
254 sync |= 4;
255 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
256 sync |= 8;
257
258 pr_debug("H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
259 htotal, hblank, hdelay, var->hsync_len,
260 vtotal, vblank, vdelay, var->vsync_len, sync);
261
262 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
263
264 hdmi_write(hdmi, htotal, HDMI_EXTERNAL_H_TOTAL_7_0);
265 hdmi_write(hdmi, htotal >> 8, HDMI_EXTERNAL_H_TOTAL_11_8);
266
267 hdmi_write(hdmi, hblank, HDMI_EXTERNAL_H_BLANK_7_0);
268 hdmi_write(hdmi, hblank >> 8, HDMI_EXTERNAL_H_BLANK_9_8);
269
270 hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0);
271 hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8);
272
273 hdmi_write(hdmi, var->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0);
274 hdmi_write(hdmi, var->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8);
275
276 hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0);
277 hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8);
278
279 hdmi_write(hdmi, vblank, HDMI_EXTERNAL_V_BLANK);
280
281 hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY);
282
283 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
284
285 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for manual mode */
286}
287
288/**
289 * sh_hdmi_video_config()
290 */
291static void sh_hdmi_video_config(struct sh_hdmi *hdmi)
292{
293 /*
294 * [7:4]: Audio sampling frequency: 48kHz
295 * [3:1]: Input video format: RGB and YCbCr 4:4:4 (Y on Green)
296 * [0]: Internal/External DE select: internal
297 */
298 hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1);
299
300 /*
301 * [7:6]: Video output format: RGB 4:4:4
302 * [5:4]: Input video data width: 8 bit
303 * [3:1]: EAV/SAV location: channel 1
304 * [0]: Video input color space: RGB
305 */
306 hdmi_write(hdmi, 0x34, HDMI_VIDEO_SETTING_1);
307
308 /*
309 * [7:6]: Together with bit [6] of HDMI_AUDIO_VIDEO_SETTING_2, which is
310 * left at 0 by default, this configures 24bpp and sets the Color Depth
311 * (CD) field in the General Control Packet
312 */
313 hdmi_write(hdmi, 0x20, HDMI_DEEP_COLOR_MODES);
314}
315
316/**
317 * sh_hdmi_audio_config()
318 */
319static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
320{
321 /*
322 * [7:4] L/R data swap control
323 * [3:0] appropriate N[19:16]
324 */
325 hdmi_write(hdmi, 0x00, HDMI_L_R_DATA_SWAP_CTRL_RPKT);
326 /* appropriate N[15:8] */
327 hdmi_write(hdmi, 0x18, HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8);
328 /* appropriate N[7:0] */
329 hdmi_write(hdmi, 0x00, HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0);
330
331 /* [7:4] 48 kHz SPDIF not used */
332 hdmi_write(hdmi, 0x20, HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS);
333
334 /*
335 * [6:5] set required down sampling rate if required
336 * [4:3] set required audio source
337 */
338 hdmi_write(hdmi, 0x00, HDMI_AUDIO_SETTING_1);
339
340 /* [3:0] set sending channel number for channel status */
341 hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2);
342
343 /*
344 * [5:2] set valid I2S source input pin
345 * [1:0] set input I2S source mode
346 */
347 hdmi_write(hdmi, 0x04, HDMI_I2S_AUDIO_SET);
348
349 /* [7:4] set valid DSD source input pin */
350 hdmi_write(hdmi, 0x00, HDMI_DSD_AUDIO_SET);
351
352 /* [7:0] set appropriate I2S input pin swap settings if required */
353 hdmi_write(hdmi, 0x00, HDMI_I2S_INPUT_PIN_SWAP);
354
355 /*
356 * [7] set validity bit for channel status
357 * [3:0] set original sample frequency for channel status
358 */
359 hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_1);
360
361 /*
362 * [7] set value for channel status
363 * [6] set value for channel status
364 * [5] set copyright bit for channel status
365 * [4:2] set additional information for channel status
366 * [1:0] set clock accuracy for channel status
367 */
368 hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_2);
369
370 /* [7:0] set category code for channel status */
371 hdmi_write(hdmi, 0x00, HDMI_CATEGORY_CODE);
372
373 /*
374 * [7:4] set source number for channel status
375 * [3:0] set word length for channel status
376 */
377 hdmi_write(hdmi, 0x00, HDMI_SOURCE_NUM_AUDIO_WORD_LEN);
378
379 /* [7:4] set sample frequency for channel status */
380 hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1);
381}
382
383/**
384 * sh_hdmi_phy_config()
385 */
386static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
387{
388 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
389 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
390 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
391 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
392 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */
393 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
394 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
395 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
396 hdmi_write(hdmi, 0x0E, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
397 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
398 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
399}
400
401/**
402 * sh_hdmi_avi_infoframe_setup() - Auxiliary Video Information InfoFrame CONTROL PACKET
403 */
404static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
405{
406 /* AVI InfoFrame */
407 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX);
408
409 /* Packet Type = 0x82 */
410 hdmi_write(hdmi, 0x82, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
411
412 /* Version = 0x02 */
413 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
414
415 /* Length = 13 (0x0D) */
416 hdmi_write(hdmi, 0x0D, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
417
418 /* N. A. Checksum */
419 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0);
420
421 /*
422 * Y = RGB
423 * A0 = No Data
424 * B = Bar Data not valid
425 * S = No Data
426 */
427 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
428
429 /*
430 * C = No Data
431 * M = 16:9 Picture Aspect Ratio
432 * R = Same as picture aspect ratio
433 */
434 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
435
436 /*
437 * ITC = No Data
438 * EC = xvYCC601
439 * Q = Default (depends on video format)
440 * SC = No Known non_uniform Scaling
441 */
442 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
443
444 /*
445 * VIC = 1280 x 720p: ignored if external config is used
446 * Send 2 for 720 x 480p, 16 for 1080p
447 */
448 hdmi_write(hdmi, 4, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
449
450 /* PR = No Repetition */
451 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
452
453 /* Line Number of End of Top Bar (lower 8 bits) */
454 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6);
455
456 /* Line Number of End of Top Bar (upper 8 bits) */
457 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7);
458
459 /* Line Number of Start of Bottom Bar (lower 8 bits) */
460 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8);
461
462 /* Line Number of Start of Bottom Bar (upper 8 bits) */
463 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9);
464
465 /* Pixel Number of End of Left Bar (lower 8 bits) */
466 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10);
467
468 /* Pixel Number of End of Left Bar (upper 8 bits) */
469 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB11);
470
471 /* Pixel Number of Start of Right Bar (lower 8 bits) */
472 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB12);
473
474 /* Pixel Number of Start of Right Bar (upper 8 bits) */
475 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB13);
476}
477
478/**
479 * sh_hdmi_audio_infoframe_setup() - Audio InfoFrame of CONTROL PACKET
480 */
481static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi)
482{
483 /* Audio InfoFrame */
484 hdmi_write(hdmi, 0x08, HDMI_CTRL_PKT_BUF_INDEX);
485
486 /* Packet Type = 0x84 */
487 hdmi_write(hdmi, 0x84, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
488
489 /* Version Number = 0x01 */
490 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
491
492 /* 0 Length = 10 (0x0A) */
493 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
494
495 /* n. a. Checksum */
496 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0);
497
498 /* Audio Channel Count = Refer to Stream Header */
499 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
500
501 /* Refer to Stream Header */
502 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
503
504 /* Format depends on coding type (i.e. CT0...CT3) */
505 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
506
507 /* Speaker Channel Allocation = Front Right + Front Left */
508 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
509
510 /* Level Shift Value = 0 dB, Down - mix is permitted or no information */
511 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
512
513 /* Reserved (0) */
514 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6);
515 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7);
516 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8);
517 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9);
518 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10);
519}
520
521/**
522 * sh_hdmi_gamut_metadata_setup() - Gamut Metadata Packet of CONTROL PACKET
523 */
524static void sh_hdmi_gamut_metadata_setup(struct sh_hdmi *hdmi)
525{
526 int i;
527
528 /* Gamut Metadata Packet */
529 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_INDEX);
530
531 /* Packet Type = 0x0A */
532 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
533 /* Gamut Packet is not used, so default value */
534 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
535 /* Gamut Packet is not used, so default value */
536 hdmi_write(hdmi, 0x10, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
537
538 /* GBD bytes 0 through 27 */
539 for (i = 0; i <= 27; i++)
540 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0_63H - PB27_7EH */
541 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
542}
543
544/**
545 * sh_hdmi_acp_setup() - Audio Content Protection Packet (ACP)
546 */
547static void sh_hdmi_acp_setup(struct sh_hdmi *hdmi)
548{
549 int i;
550
551 /* Audio Content Protection Packet (ACP) */
552 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_INDEX);
553
554 /* Packet Type = 0x04 */
555 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
556 /* ACP_Type */
557 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
558 /* Reserved (0) */
559 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
560
561 /* GBD bytes 0 through 27 */
562 for (i = 0; i <= 27; i++)
563 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
564 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
565}
566
567/**
568 * sh_hdmi_isrc1_setup() - ISRC1 Packet
569 */
570static void sh_hdmi_isrc1_setup(struct sh_hdmi *hdmi)
571{
572 int i;
573
574 /* ISRC1 Packet */
575 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_INDEX);
576
577 /* Packet Type = 0x05 */
578 hdmi_write(hdmi, 0x05, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
579 /* ISRC_Cont, ISRC_Valid, Reserved (0), ISRC_Status */
580 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
581 /* Reserved (0) */
582 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
583
584 /* PB0 UPC_EAN_ISRC_0-15 */
585 /* Bytes PB16-PB27 shall be set to a value of 0. */
586 for (i = 0; i <= 27; i++)
587 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
588 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
589}
590
591/**
592 * sh_hdmi_isrc2_setup() - ISRC2 Packet
593 */
594static void sh_hdmi_isrc2_setup(struct sh_hdmi *hdmi)
595{
596 int i;
597
598 /* ISRC2 Packet */
599 hdmi_write(hdmi, 0x03, HDMI_CTRL_PKT_BUF_INDEX);
600
601 /* HB0 Packet Type = 0x06 */
602 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
603 /* Reserved (0) */
604 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
605 /* Reserved (0) */
606 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
607
608 /* PB0 UPC_EAN_ISRC_16-31 */
609 /* Bytes PB16-PB27 shall be set to a value of 0. */
610 for (i = 0; i <= 27; i++)
611 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
612 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
613}
614
615/**
616 * sh_hdmi_configure() - Initialise HDMI for output
617 */
618static void sh_hdmi_configure(struct sh_hdmi *hdmi)
619{
620 /* Configure video format */
621 sh_hdmi_video_config(hdmi);
622
623 /* Configure audio format */
624 sh_hdmi_audio_config(hdmi);
625
626 /* Configure PHY */
627 sh_hdmi_phy_config(hdmi);
628
629 /* Auxiliary Video Information (AVI) InfoFrame */
630 sh_hdmi_avi_infoframe_setup(hdmi);
631
632 /* Audio InfoFrame */
633 sh_hdmi_audio_infoframe_setup(hdmi);
634
635 /* Gamut Metadata packet */
636 sh_hdmi_gamut_metadata_setup(hdmi);
637
638 /* Audio Content Protection (ACP) Packet */
639 sh_hdmi_acp_setup(hdmi);
640
641 /* ISRC1 Packet */
642 sh_hdmi_isrc1_setup(hdmi);
643
644 /* ISRC2 Packet */
645 sh_hdmi_isrc2_setup(hdmi);
646
647 /*
648 * Control packet auto send with VSYNC control: auto send
649 * General control, Gamut metadata, ISRC, and ACP packets
650 */
651 hdmi_write(hdmi, 0x8E, HDMI_CTRL_PKT_AUTO_SEND);
652
653 /* FIXME */
654 msleep(10);
655
656 /* PS mode b->d, reset PLLA and PLLB */
657 hdmi_write(hdmi, 0x4C, HDMI_SYSTEM_CTRL);
658
659 udelay(10);
660
661 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
662}
663
664static void sh_hdmi_read_edid(struct sh_hdmi *hdmi)
665{
666 struct fb_var_screeninfo *var = &hdmi->var;
667 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
668 struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg;
669 unsigned long height = var->height, width = var->width;
670 int i;
671 u8 edid[128];
672
673 /* Read EDID */
674 pr_debug("Read back EDID code:");
675 for (i = 0; i < 128; i++) {
676 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
677#ifdef DEBUG
678 if ((i % 16) == 0) {
679 printk(KERN_CONT "\n");
680 printk(KERN_DEBUG "%02X | %02X", i, edid[i]);
681 } else {
682 printk(KERN_CONT " %02X", edid[i]);
683 }
684#endif
685 }
686#ifdef DEBUG
687 printk(KERN_CONT "\n");
688#endif
689 fb_parse_edid(edid, var);
690 pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n",
691 var->left_margin, var->xres, var->right_margin, var->hsync_len,
692 var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
693 PICOS2KHZ(var->pixclock));
694
695 /* FIXME: Use user-provided configuration instead of EDID */
696 var->width = width;
697 var->xres = lcd_cfg->xres;
698 var->xres_virtual = lcd_cfg->xres;
699 var->left_margin = lcd_cfg->left_margin;
700 var->right_margin = lcd_cfg->right_margin;
701 var->hsync_len = lcd_cfg->hsync_len;
702 var->height = height;
703 var->yres = lcd_cfg->yres;
704 var->yres_virtual = lcd_cfg->yres * 2;
705 var->upper_margin = lcd_cfg->upper_margin;
706 var->lower_margin = lcd_cfg->lower_margin;
707 var->vsync_len = lcd_cfg->vsync_len;
708 var->sync = lcd_cfg->sync;
709 var->pixclock = lcd_cfg->pixclock;
710
711 hdmi_external_video_param(hdmi);
712}
713
714static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
715{
716 struct sh_hdmi *hdmi = dev_id;
717 u8 status1, status2, mask1, mask2;
718
719 /* mode_b and PLLA and PLLB reset */
720 hdmi_write(hdmi, 0x2C, HDMI_SYSTEM_CTRL);
721
722 /* How long shall reset be held? */
723 udelay(10);
724
725 /* mode_b and PLLA and PLLB reset release */
726 hdmi_write(hdmi, 0x20, HDMI_SYSTEM_CTRL);
727
728 status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1);
729 status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2);
730
731 mask1 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_1);
732 mask2 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_2);
733
734 /* Correct would be to ack only set bits, but the datasheet requires 0xff */
735 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_1);
736 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2);
737
738 if (printk_ratelimit())
739 pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n",
740 irq, status1, mask1, status2, mask2);
741
742 if (!((status1 & mask1) | (status2 & mask2))) {
743 return IRQ_NONE;
744 } else if (status1 & 0xc0) {
745 u8 msens;
746
747 /* Datasheet specifies 10ms... */
748 udelay(500);
749
750 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS);
751 pr_debug("MSENS 0x%x\n", msens);
752 /* Check, if hot plug & MSENS pin status are both high */
753 if ((msens & 0xC0) == 0xC0) {
754 /* Display plug in */
755 hdmi->hp_state = HDMI_HOTPLUG_CONNECTED;
756
757 /* Set EDID word address */
758 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
759 /* Set EDID segment pointer */
760 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
761 /* Enable EDID interrupt */
762 hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
763 } else if (!(status1 & 0x80)) {
764 /* Display unplug, beware multiple interrupts */
765 if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED)
766 schedule_delayed_work(&hdmi->edid_work, 0);
767
768 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
769 /* display_off will switch back to mode_a */
770 }
771 } else if (status1 & 2) {
772 /* EDID error interrupt: retry */
773 /* Set EDID word address */
774 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
775 /* Set EDID segment pointer */
776 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
777 } else if (status1 & 4) {
778 /* Disable EDID interrupt */
779 hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1);
780 hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
781 schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10));
782 }
783
784 return IRQ_HANDLED;
785}
786
787static void hdmi_display_on(void *arg, struct fb_info *info)
788{
789 struct sh_hdmi *hdmi = arg;
790 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
791
792 if (info->var.xres != 1280 || info->var.yres != 720) {
793 dev_warn(info->device, "Unsupported framebuffer geometry %ux%u\n",
794 info->var.xres, info->var.yres);
795 return;
796 }
797
798 pr_debug("%s(%p): state %x\n", __func__, pdata->lcd_dev, info->state);
799 /*
800 * FIXME: not a good place to store fb_info. And we cannot nullify it
801 * even on monitor disconnect. What should the lifecycle be?
802 */
803 hdmi->info = info;
804 switch (hdmi->hp_state) {
805 case HDMI_HOTPLUG_EDID_DONE:
806 /* PS mode d->e. All functions are active */
807 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
808 pr_debug("HDMI running\n");
809 break;
810 case HDMI_HOTPLUG_DISCONNECTED:
811 info->state = FBINFO_STATE_SUSPENDED;
812 default:
813 hdmi->var = info->var;
814 }
815}
816
817static void hdmi_display_off(void *arg)
818{
819 struct sh_hdmi *hdmi = arg;
820 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
821
822 pr_debug("%s(%p)\n", __func__, pdata->lcd_dev);
823 /* PS mode e->a */
824 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
825}
826
827/* Hotplug interrupt occurred, read EDID */
828static void edid_work_fn(struct work_struct *work)
829{
830 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
831 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
832
833 pr_debug("%s(%p): begin, hotplug status %d\n", __func__,
834 pdata->lcd_dev, hdmi->hp_state);
835
836 if (!pdata->lcd_dev)
837 return;
838
839 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
840 pm_runtime_get_sync(hdmi->dev);
841 /* A device has been plugged in */
842 sh_hdmi_read_edid(hdmi);
843 msleep(10);
844 sh_hdmi_configure(hdmi);
845 /* Switched to another (d) power-save mode */
846 msleep(10);
847
848 if (!hdmi->info)
849 return;
850
851 acquire_console_sem();
852
853 /* HDMI plug in */
854 hdmi->info->var = hdmi->var;
855 if (hdmi->info->state != FBINFO_STATE_RUNNING)
856 fb_set_suspend(hdmi->info, 0);
857 else
858 hdmi_display_on(hdmi, hdmi->info);
859
860 release_console_sem();
861 } else {
862 if (!hdmi->info)
863 return;
864
865 acquire_console_sem();
866
867 /* HDMI disconnect */
868 fb_set_suspend(hdmi->info, 1);
869
870 release_console_sem();
871 pm_runtime_put(hdmi->dev);
872 }
873
874 pr_debug("%s(%p): end\n", __func__, pdata->lcd_dev);
875}
876
877static int __init sh_hdmi_probe(struct platform_device *pdev)
878{
879 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
880 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
881 int irq = platform_get_irq(pdev, 0), ret;
882 struct sh_hdmi *hdmi;
883 long rate;
884
885 if (!res || !pdata || irq < 0)
886 return -ENODEV;
887
888 hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
889 if (!hdmi) {
890 dev_err(&pdev->dev, "Cannot allocate device data\n");
891 return -ENOMEM;
892 }
893
894 hdmi->dev = &pdev->dev;
895
896 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
897 if (IS_ERR(hdmi->hdmi_clk)) {
898 ret = PTR_ERR(hdmi->hdmi_clk);
899 dev_err(&pdev->dev, "Unable to get clock: %d\n", ret);
900 goto egetclk;
901 }
902
903 rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000;
904
905 rate = clk_round_rate(hdmi->hdmi_clk, rate);
906 if (rate < 0) {
907 ret = rate;
908 dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate);
909 goto erate;
910 }
911
912 ret = clk_set_rate(hdmi->hdmi_clk, rate);
913 if (ret < 0) {
914 dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret);
915 goto erate;
916 }
917
918 pr_debug("HDMI set frequency %lu\n", rate);
919
920 ret = clk_enable(hdmi->hdmi_clk);
921 if (ret < 0) {
922 dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret);
923 goto eclkenable;
924 }
925
926 dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
927
928 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
929 dev_err(&pdev->dev, "HDMI register region already claimed\n");
930 ret = -EBUSY;
931 goto ereqreg;
932 }
933
934 hdmi->base = ioremap(res->start, resource_size(res));
935 if (!hdmi->base) {
936 dev_err(&pdev->dev, "HDMI register region already claimed\n");
937 ret = -ENOMEM;
938 goto emap;
939 }
940
941 platform_set_drvdata(pdev, hdmi);
942
943#if 1
944 /* Product and revision IDs are 0 in sh-mobile version */
945 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
946 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
947#endif
948
949 /* Set up LCDC callbacks */
950 pdata->lcd_chan->board_cfg.board_data = hdmi;
951 pdata->lcd_chan->board_cfg.display_on = hdmi_display_on;
952 pdata->lcd_chan->board_cfg.display_off = hdmi_display_off;
953
954 INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn);
955
956 pm_runtime_enable(&pdev->dev);
957 pm_runtime_resume(&pdev->dev);
958
959 ret = request_irq(irq, sh_hdmi_hotplug, 0,
960 dev_name(&pdev->dev), hdmi);
961 if (ret < 0) {
962 dev_err(&pdev->dev, "Unable to request irq: %d\n", ret);
963 goto ereqirq;
964 }
965
966 return 0;
967
968ereqirq:
969 pm_runtime_disable(&pdev->dev);
970 iounmap(hdmi->base);
971emap:
972 release_mem_region(res->start, resource_size(res));
973ereqreg:
974 clk_disable(hdmi->hdmi_clk);
975eclkenable:
976erate:
977 clk_put(hdmi->hdmi_clk);
978egetclk:
979 kfree(hdmi);
980
981 return ret;
982}
983
984static int __exit sh_hdmi_remove(struct platform_device *pdev)
985{
986 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
987 struct sh_hdmi *hdmi = platform_get_drvdata(pdev);
988 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
989 int irq = platform_get_irq(pdev, 0);
990
991 pdata->lcd_chan->board_cfg.display_on = NULL;
992 pdata->lcd_chan->board_cfg.display_off = NULL;
993 pdata->lcd_chan->board_cfg.board_data = NULL;
994
995 free_irq(irq, hdmi);
996 pm_runtime_disable(&pdev->dev);
997 cancel_delayed_work_sync(&hdmi->edid_work);
998 clk_disable(hdmi->hdmi_clk);
999 clk_put(hdmi->hdmi_clk);
1000 iounmap(hdmi->base);
1001 release_mem_region(res->start, resource_size(res));
1002 kfree(hdmi);
1003
1004 return 0;
1005}
1006
1007static struct platform_driver sh_hdmi_driver = {
1008 .remove = __exit_p(sh_hdmi_remove),
1009 .driver = {
1010 .name = "sh-mobile-hdmi",
1011 },
1012};
1013
1014static int __init sh_hdmi_init(void)
1015{
1016 return platform_driver_probe(&sh_hdmi_driver, sh_hdmi_probe);
1017}
1018module_init(sh_hdmi_init);
1019
1020static void __exit sh_hdmi_exit(void)
1021{
1022 platform_driver_unregister(&sh_hdmi_driver);
1023}
1024module_exit(sh_hdmi_exit);
1025
1026MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
1027MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver");
1028MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 12c451a711e..d72075a9f01 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -56,6 +56,7 @@ static int lcdc_shared_regs[] = {
56/* per-channel registers */ 56/* per-channel registers */
57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, 57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR, 58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
59 LDHAJR,
59 NR_CH_REGS }; 60 NR_CH_REGS };
60 61
61static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 62static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
@@ -74,6 +75,7 @@ static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
74 [LDVLNR] = 0x450, 75 [LDVLNR] = 0x450,
75 [LDVSYNR] = 0x454, 76 [LDVSYNR] = 0x454,
76 [LDPMR] = 0x460, 77 [LDPMR] = 0x460,
78 [LDHAJR] = 0x4a0,
77}; 79};
78 80
79static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { 81static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
@@ -137,6 +139,7 @@ struct sh_mobile_lcdc_priv {
137 struct clk *dot_clk; 139 struct clk *dot_clk;
138 unsigned long lddckr; 140 unsigned long lddckr;
139 struct sh_mobile_lcdc_chan ch[2]; 141 struct sh_mobile_lcdc_chan ch[2];
142 struct notifier_block notifier;
140 unsigned long saved_shared_regs[NR_SHARED_REGS]; 143 unsigned long saved_shared_regs[NR_SHARED_REGS];
141 int started; 144 int started;
142}; 145};
@@ -404,6 +407,56 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
404 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */ 407 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
405} 408}
406 409
410static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
411{
412 struct fb_var_screeninfo *var = &ch->info->var;
413 unsigned long h_total, hsync_pos;
414 u32 tmp;
415
416 tmp = ch->ldmt1r_value;
417 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
418 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
419 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
420 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
421 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
422 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
423 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
424 lcdc_write_chan(ch, LDMT1R, tmp);
425
426 /* setup SYS bus */
427 lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
428 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
429
430 /* horizontal configuration */
431 h_total = var->xres + var->hsync_len +
432 var->left_margin + var->right_margin;
433 tmp = h_total / 8; /* HTCN */
434 tmp |= (var->xres / 8) << 16; /* HDCN */
435 lcdc_write_chan(ch, LDHCNR, tmp);
436
437 hsync_pos = var->xres + var->right_margin;
438 tmp = hsync_pos / 8; /* HSYNP */
439 tmp |= (var->hsync_len / 8) << 16; /* HSYNW */
440 lcdc_write_chan(ch, LDHSYNR, tmp);
441
442 /* vertical configuration */
443 tmp = var->yres + var->vsync_len +
444 var->upper_margin + var->lower_margin; /* VTLN */
445 tmp |= var->yres << 16; /* VDLN */
446 lcdc_write_chan(ch, LDVLNR, tmp);
447
448 tmp = var->yres + var->lower_margin; /* VSYNP */
449 tmp |= var->vsync_len << 16; /* VSYNW */
450 lcdc_write_chan(ch, LDVSYNR, tmp);
451
452 /* Adjust horizontal synchronisation for HDMI */
453 tmp = ((var->xres & 7) << 24) |
454 ((h_total & 7) << 16) |
455 ((var->hsync_len & 7) << 8) |
456 hsync_pos;
457 lcdc_write_chan(ch, LDHAJR, tmp);
458}
459
407static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 460static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
408{ 461{
409 struct sh_mobile_lcdc_chan *ch; 462 struct sh_mobile_lcdc_chan *ch;
@@ -470,49 +523,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
470 if (!ch->enabled) 523 if (!ch->enabled)
471 continue; 524 continue;
472 525
473 tmp = ch->ldmt1r_value; 526 sh_mobile_lcdc_geometry(ch);
474 tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
475 tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
476 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
477 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
478 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
479 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
480 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
481 lcdc_write_chan(ch, LDMT1R, tmp);
482
483 /* setup SYS bus */
484 lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
485 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
486
487 /* horizontal configuration */
488 tmp = lcd_cfg->xres + lcd_cfg->hsync_len;
489 tmp += lcd_cfg->left_margin;
490 tmp += lcd_cfg->right_margin;
491 tmp /= 8; /* HTCN */
492 tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */
493 lcdc_write_chan(ch, LDHCNR, tmp);
494
495 tmp = lcd_cfg->xres;
496 tmp += lcd_cfg->right_margin;
497 tmp /= 8; /* HSYNP */
498 tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */
499 lcdc_write_chan(ch, LDHSYNR, tmp);
500 527
501 /* power supply */ 528 /* power supply */
502 lcdc_write_chan(ch, LDPMR, 0); 529 lcdc_write_chan(ch, LDPMR, 0);
503 530
504 /* vertical configuration */
505 tmp = lcd_cfg->yres + lcd_cfg->vsync_len;
506 tmp += lcd_cfg->upper_margin;
507 tmp += lcd_cfg->lower_margin; /* VTLN */
508 tmp |= lcd_cfg->yres << 16; /* VDLN */
509 lcdc_write_chan(ch, LDVLNR, tmp);
510
511 tmp = lcd_cfg->yres;
512 tmp += lcd_cfg->lower_margin; /* VSYNP */
513 tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */
514 lcdc_write_chan(ch, LDVSYNR, tmp);
515
516 board_cfg = &ch->cfg.board_cfg; 531 board_cfg = &ch->cfg.board_cfg;
517 if (board_cfg->setup_sys) 532 if (board_cfg->setup_sys)
518 ret = board_cfg->setup_sys(board_cfg->board_data, ch, 533 ret = board_cfg->setup_sys(board_cfg->board_data, ch,
@@ -577,7 +592,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
577 592
578 board_cfg = &ch->cfg.board_cfg; 593 board_cfg = &ch->cfg.board_cfg;
579 if (board_cfg->display_on) 594 if (board_cfg->display_on)
580 board_cfg->display_on(board_cfg->board_data); 595 board_cfg->display_on(board_cfg->board_data, ch->info);
581 } 596 }
582 597
583 return 0; 598 return 0;
@@ -943,6 +958,62 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
943 .runtime_resume = sh_mobile_lcdc_runtime_resume, 958 .runtime_resume = sh_mobile_lcdc_runtime_resume,
944}; 959};
945 960
961static int sh_mobile_lcdc_notify(struct notifier_block *nb,
962 unsigned long action, void *data)
963{
964 struct fb_event *event = data;
965 struct fb_info *info = event->info;
966 struct sh_mobile_lcdc_chan *ch = info->par;
967 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
968 struct fb_var_screeninfo *var;
969
970 if (&ch->lcdc->notifier != nb)
971 return 0;
972
973 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
974 __func__, action, event->data);
975
976 switch(action) {
977 case FB_EVENT_SUSPEND:
978 if (board_cfg->display_off)
979 board_cfg->display_off(board_cfg->board_data);
980 pm_runtime_put(info->device);
981 break;
982 case FB_EVENT_RESUME:
983 var = &info->var;
984
985 /* HDMI must be enabled before LCDC configuration */
986 if (board_cfg->display_on)
987 board_cfg->display_on(board_cfg->board_data, ch->info);
988
989 /* Check if the new display is not in our modelist */
990 if (ch->info->modelist.next &&
991 !fb_match_mode(var, &ch->info->modelist)) {
992 struct fb_videomode mode;
993 int ret;
994
995 /* Can we handle this display? */
996 if (var->xres > ch->cfg.lcd_cfg.xres ||
997 var->yres > ch->cfg.lcd_cfg.yres)
998 return -ENOMEM;
999
1000 /* Add to the modelist */
1001 fb_var_to_videomode(&mode, var);
1002 ret = fb_add_videomode(&mode, &ch->info->modelist);
1003 if (ret < 0)
1004 return ret;
1005 }
1006
1007 pm_runtime_get_sync(info->device);
1008
1009 sh_mobile_lcdc_geometry(ch);
1010
1011 break;
1012 }
1013
1014 return 0;
1015}
1016
946static int sh_mobile_lcdc_remove(struct platform_device *pdev); 1017static int sh_mobile_lcdc_remove(struct platform_device *pdev);
947 1018
948static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) 1019static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
@@ -1020,15 +1091,19 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1020 goto err1; 1091 goto err1;
1021 } 1092 }
1022 1093
1094 priv->base = ioremap_nocache(res->start, resource_size(res));
1095 if (!priv->base)
1096 goto err1;
1097
1023 error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv); 1098 error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv);
1024 if (error) { 1099 if (error) {
1025 dev_err(&pdev->dev, "unable to setup clocks\n"); 1100 dev_err(&pdev->dev, "unable to setup clocks\n");
1026 goto err1; 1101 goto err1;
1027 } 1102 }
1028 1103
1029 priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
1030
1031 for (i = 0; i < j; i++) { 1104 for (i = 0; i < j; i++) {
1105 struct fb_var_screeninfo *var;
1106 struct fb_videomode *lcd_cfg;
1032 cfg = &priv->ch[i].cfg; 1107 cfg = &priv->ch[i].cfg;
1033 1108
1034 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); 1109 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev);
@@ -1039,22 +1114,33 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1039 } 1114 }
1040 1115
1041 info = priv->ch[i].info; 1116 info = priv->ch[i].info;
1117 var = &info->var;
1118 lcd_cfg = &cfg->lcd_cfg;
1042 info->fbops = &sh_mobile_lcdc_ops; 1119 info->fbops = &sh_mobile_lcdc_ops;
1043 info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; 1120 var->xres = var->xres_virtual = lcd_cfg->xres;
1044 info->var.yres = cfg->lcd_cfg.yres; 1121 var->yres = lcd_cfg->yres;
1045 /* Default Y virtual resolution is 2x panel size */ 1122 /* Default Y virtual resolution is 2x panel size */
1046 info->var.yres_virtual = info->var.yres * 2; 1123 var->yres_virtual = var->yres * 2;
1047 info->var.width = cfg->lcd_size_cfg.width; 1124 var->width = cfg->lcd_size_cfg.width;
1048 info->var.height = cfg->lcd_size_cfg.height; 1125 var->height = cfg->lcd_size_cfg.height;
1049 info->var.activate = FB_ACTIVATE_NOW; 1126 var->activate = FB_ACTIVATE_NOW;
1050 error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp); 1127 var->left_margin = lcd_cfg->left_margin;
1128 var->right_margin = lcd_cfg->right_margin;
1129 var->upper_margin = lcd_cfg->upper_margin;
1130 var->lower_margin = lcd_cfg->lower_margin;
1131 var->hsync_len = lcd_cfg->hsync_len;
1132 var->vsync_len = lcd_cfg->vsync_len;
1133 var->sync = lcd_cfg->sync;
1134 var->pixclock = lcd_cfg->pixclock;
1135
1136 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp);
1051 if (error) 1137 if (error)
1052 break; 1138 break;
1053 1139
1054 info->fix = sh_mobile_lcdc_fix; 1140 info->fix = sh_mobile_lcdc_fix;
1055 info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8); 1141 info->fix.line_length = lcd_cfg->xres * (cfg->bpp / 8);
1056 info->fix.smem_len = info->fix.line_length * 1142 info->fix.smem_len = info->fix.line_length *
1057 info->var.yres_virtual; 1143 var->yres_virtual;
1058 1144
1059 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, 1145 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
1060 &priv->ch[i].dma_handle, GFP_KERNEL); 1146 &priv->ch[i].dma_handle, GFP_KERNEL);
@@ -1119,10 +1205,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1119 ch->cfg.bpp); 1205 ch->cfg.bpp);
1120 1206
1121 /* deferred io mode: disable clock to save power */ 1207 /* deferred io mode: disable clock to save power */
1122 if (info->fbdefio) 1208 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
1123 sh_mobile_lcdc_clk_off(priv); 1209 sh_mobile_lcdc_clk_off(priv);
1124 } 1210 }
1125 1211
1212 /* Failure ignored */
1213 priv->notifier.notifier_call = sh_mobile_lcdc_notify;
1214 fb_register_client(&priv->notifier);
1215
1126 return 0; 1216 return 0;
1127err1: 1217err1:
1128 sh_mobile_lcdc_remove(pdev); 1218 sh_mobile_lcdc_remove(pdev);
@@ -1136,6 +1226,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1136 struct fb_info *info; 1226 struct fb_info *info;
1137 int i; 1227 int i;
1138 1228
1229 fb_unregister_client(&priv->notifier);
1230
1139 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 1231 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1140 if (priv->ch[i].info && priv->ch[i].info->dev) 1232 if (priv->ch[i].info && priv->ch[i].info->dev)
1141 unregister_framebuffer(priv->ch[i].info); 1233 unregister_framebuffer(priv->ch[i].info);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index f10db6e5f3b..522832023a6 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -186,6 +186,9 @@
186#define PORT_ALTERA_JTAGUART 91 186#define PORT_ALTERA_JTAGUART 91
187#define PORT_ALTERA_UART 92 187#define PORT_ALTERA_UART 92
188 188
189/* SH-SCI */
190#define PORT_SCIFB 93
191
189#ifdef __KERNEL__ 192#ifdef __KERNEL__
190 193
191#include <linux/compiler.h> 194#include <linux/compiler.h>
diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
index 1636d1e2a5f..875ce50719a 100644
--- a/include/linux/sh_clk.h
+++ b/include/linux/sh_clk.h
@@ -25,6 +25,10 @@ struct clk {
25 int id; 25 int id;
26 26
27 struct clk *parent; 27 struct clk *parent;
28 struct clk **parent_table; /* list of parents to */
29 unsigned short parent_num; /* choose between */
30 unsigned char src_shift; /* source clock field in the */
31 unsigned char src_width; /* configuration register */
28 struct clk_ops *ops; 32 struct clk_ops *ops;
29 33
30 struct list_head children; 34 struct list_head children;
@@ -138,13 +142,22 @@ int sh_clk_div4_enable_register(struct clk *clks, int nr,
138int sh_clk_div4_reparent_register(struct clk *clks, int nr, 142int sh_clk_div4_reparent_register(struct clk *clks, int nr,
139 struct clk_div4_table *table); 143 struct clk_div4_table *table);
140 144
141#define SH_CLK_DIV6(_parent, _reg, _flags) \ 145#define SH_CLK_DIV6_EXT(_parent, _reg, _flags, _parents, \
142{ \ 146 _num_parents, _src_shift, _src_width) \
143 .parent = _parent, \ 147{ \
144 .enable_reg = (void __iomem *)_reg, \ 148 .parent = _parent, \
145 .flags = _flags, \ 149 .enable_reg = (void __iomem *)_reg, \
150 .flags = _flags, \
151 .parent_table = _parents, \
152 .parent_num = _num_parents, \
153 .src_shift = _src_shift, \
154 .src_width = _src_width, \
146} 155}
147 156
157#define SH_CLK_DIV6(_parent, _reg, _flags) \
158 SH_CLK_DIV6_EXT(_parent, _reg, _flags, NULL, 0, 0, 0)
159
148int sh_clk_div6_register(struct clk *clks, int nr); 160int sh_clk_div6_register(struct clk *clks, int nr);
161int sh_clk_div6_reparent_register(struct clk *clks, int nr);
149 162
150#endif /* __SH_CLOCK_H */ 163#endif /* __SH_CLOCK_H */
diff --git a/include/video/mipi_display.h b/include/video/mipi_display.h
new file mode 100644
index 00000000000..ddcc8ca7316
--- /dev/null
+++ b/include/video/mipi_display.h
@@ -0,0 +1,130 @@
1/*
2 * Defines for Mobile Industry Processor Interface (MIPI(R))
3 * Display Working Group standards: DSI, DCS, DBI, DPI
4 *
5 * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
6 * Copyright (C) 2006 Nokia Corporation
7 * Author: Imre Deak <imre.deak@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#ifndef MIPI_DISPLAY_H
14#define MIPI_DISPLAY_H
15
16/* MIPI DSI Processor-to-Peripheral transaction types */
17enum {
18 MIPI_DSI_V_SYNC_START = 0x01,
19 MIPI_DSI_V_SYNC_END = 0x11,
20 MIPI_DSI_H_SYNC_START = 0x21,
21 MIPI_DSI_H_SYNC_END = 0x31,
22
23 MIPI_DSI_COLOR_MODE_OFF = 0x02,
24 MIPI_DSI_COLOR_MODE_ON = 0x12,
25 MIPI_DSI_SHUTDOWN_PERIPHERAL = 0x22,
26 MIPI_DSI_TURN_ON_PERIPHERAL = 0x32,
27
28 MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM = 0x03,
29 MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM = 0x13,
30 MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM = 0x23,
31
32 MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM = 0x04,
33 MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM = 0x14,
34 MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM = 0x24,
35
36 MIPI_DSI_DCS_SHORT_WRITE = 0x05,
37 MIPI_DSI_DCS_SHORT_WRITE_PARAM = 0x15,
38
39 MIPI_DSI_DCS_READ = 0x06,
40
41 MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE = 0x37,
42
43 MIPI_DSI_END_OF_TRANSMISSION = 0x08,
44
45 MIPI_DSI_NULL_PACKET = 0x09,
46 MIPI_DSI_BLANKING_PACKET = 0x19,
47 MIPI_DSI_GENERIC_LONG_WRITE = 0x29,
48 MIPI_DSI_DCS_LONG_WRITE = 0x39,
49
50 MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20 = 0x0c,
51 MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24 = 0x1c,
52 MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16 = 0x2c,
53
54 MIPI_DSI_PACKED_PIXEL_STREAM_30 = 0x0d,
55 MIPI_DSI_PACKED_PIXEL_STREAM_36 = 0x1d,
56 MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12 = 0x3d,
57
58 MIPI_DSI_PACKED_PIXEL_STREAM_16 = 0x0e,
59 MIPI_DSI_PACKED_PIXEL_STREAM_18 = 0x1e,
60 MIPI_DSI_PIXEL_STREAM_3BYTE_18 = 0x2e,
61 MIPI_DSI_PACKED_PIXEL_STREAM_24 = 0x3e,
62};
63
64/* MIPI DSI Peripheral-to-Processor transaction types */
65enum {
66 MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT = 0x02,
67 MIPI_DSI_RX_END_OF_TRANSMISSION = 0x08,
68 MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE = 0x11,
69 MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE = 0x12,
70 MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE = 0x1a,
71 MIPI_DSI_RX_DCS_LONG_READ_RESPONSE = 0x1c,
72 MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE = 0x21,
73 MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE = 0x22,
74};
75
76/* MIPI DCS commands */
77enum {
78 MIPI_DCS_NOP = 0x00,
79 MIPI_DCS_SOFT_RESET = 0x01,
80 MIPI_DCS_GET_DISPLAY_ID = 0x04,
81 MIPI_DCS_GET_RED_CHANNEL = 0x06,
82 MIPI_DCS_GET_GREEN_CHANNEL = 0x07,
83 MIPI_DCS_GET_BLUE_CHANNEL = 0x08,
84 MIPI_DCS_GET_DISPLAY_STATUS = 0x09,
85 MIPI_DCS_GET_POWER_MODE = 0x0A,
86 MIPI_DCS_GET_ADDRESS_MODE = 0x0B,
87 MIPI_DCS_GET_PIXEL_FORMAT = 0x0C,
88 MIPI_DCS_GET_DISPLAY_MODE = 0x0D,
89 MIPI_DCS_GET_SIGNAL_MODE = 0x0E,
90 MIPI_DCS_GET_DIAGNOSTIC_RESULT = 0x0F,
91 MIPI_DCS_ENTER_SLEEP_MODE = 0x10,
92 MIPI_DCS_EXIT_SLEEP_MODE = 0x11,
93 MIPI_DCS_ENTER_PARTIAL_MODE = 0x12,
94 MIPI_DCS_ENTER_NORMAL_MODE = 0x13,
95 MIPI_DCS_EXIT_INVERT_MODE = 0x20,
96 MIPI_DCS_ENTER_INVERT_MODE = 0x21,
97 MIPI_DCS_SET_GAMMA_CURVE = 0x26,
98 MIPI_DCS_SET_DISPLAY_OFF = 0x28,
99 MIPI_DCS_SET_DISPLAY_ON = 0x29,
100 MIPI_DCS_SET_COLUMN_ADDRESS = 0x2A,
101 MIPI_DCS_SET_PAGE_ADDRESS = 0x2B,
102 MIPI_DCS_WRITE_MEMORY_START = 0x2C,
103 MIPI_DCS_WRITE_LUT = 0x2D,
104 MIPI_DCS_READ_MEMORY_START = 0x2E,
105 MIPI_DCS_SET_PARTIAL_AREA = 0x30,
106 MIPI_DCS_SET_SCROLL_AREA = 0x33,
107 MIPI_DCS_SET_TEAR_OFF = 0x34,
108 MIPI_DCS_SET_TEAR_ON = 0x35,
109 MIPI_DCS_SET_ADDRESS_MODE = 0x36,
110 MIPI_DCS_SET_SCROLL_START = 0x37,
111 MIPI_DCS_EXIT_IDLE_MODE = 0x38,
112 MIPI_DCS_ENTER_IDLE_MODE = 0x39,
113 MIPI_DCS_SET_PIXEL_FORMAT = 0x3A,
114 MIPI_DCS_WRITE_MEMORY_CONTINUE = 0x3C,
115 MIPI_DCS_READ_MEMORY_CONTINUE = 0x3E,
116 MIPI_DCS_SET_TEAR_SCANLINE = 0x44,
117 MIPI_DCS_GET_SCANLINE = 0x45,
118 MIPI_DCS_READ_DDB_START = 0xA1,
119 MIPI_DCS_READ_DDB_CONTINUE = 0xA8,
120};
121
122/* MIPI DCS pixel formats */
123#define MIPI_DCS_PIXEL_FMT_24BIT 7
124#define MIPI_DCS_PIXEL_FMT_18BIT 6
125#define MIPI_DCS_PIXEL_FMT_16BIT 5
126#define MIPI_DCS_PIXEL_FMT_12BIT 3
127#define MIPI_DCS_PIXEL_FMT_8BIT 2
128#define MIPI_DCS_PIXEL_FMT_3BIT 1
129
130#endif
diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h
new file mode 100644
index 00000000000..18bca08f9f5
--- /dev/null
+++ b/include/video/sh_mipi_dsi.h
@@ -0,0 +1,35 @@
1/*
2 * Public SH-mobile MIPI DSI header
3 *
4 * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
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#ifndef VIDEO_SH_MIPI_DSI_H
11#define VIDEO_SH_MIPI_DSI_H
12
13enum sh_mipi_dsi_data_fmt {
14 MIPI_RGB888,
15 MIPI_RGB565,
16 MIPI_RGB666_LP,
17 MIPI_RGB666,
18 MIPI_BGR888,
19 MIPI_BGR565,
20 MIPI_BGR666_LP,
21 MIPI_BGR666,
22 MIPI_YUYV,
23 MIPI_UYVY,
24 MIPI_YUV420_L,
25 MIPI_YUV420,
26};
27
28struct sh_mobile_lcdc_chan_cfg;
29
30struct sh_mipi_dsi_info {
31 enum sh_mipi_dsi_data_fmt data_format;
32 struct sh_mobile_lcdc_chan_cfg *lcd_chan;
33};
34
35#endif
diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
new file mode 100644
index 00000000000..577cf18cce8
--- /dev/null
+++ b/include/video/sh_mobile_hdmi.h
@@ -0,0 +1,22 @@
1/*
2 * SH-Mobile High-Definition Multimedia Interface (HDMI)
3 *
4 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
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
11#ifndef SH_MOBILE_HDMI_H
12#define SH_MOBILE_HDMI_H
13
14struct sh_mobile_lcdc_chan_cfg;
15struct device;
16
17struct sh_mobile_hdmi_info {
18 struct sh_mobile_lcdc_chan_cfg *lcd_chan;
19 struct device *lcd_dev;
20};
21
22#endif
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index 28820545771..55d700e8566 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -3,24 +3,27 @@
3 3
4#include <linux/fb.h> 4#include <linux/fb.h>
5 5
6enum { RGB8, /* 24bpp, 8:8:8 */ 6enum {
7 RGB9, /* 18bpp, 9:9 */ 7 RGB8, /* 24bpp, 8:8:8 */
8 RGB12A, /* 24bpp, 12:12 */ 8 RGB9, /* 18bpp, 9:9 */
9 RGB12B, /* 12bpp */ 9 RGB12A, /* 24bpp, 12:12 */
10 RGB16, /* 16bpp */ 10 RGB12B, /* 12bpp */
11 RGB18, /* 18bpp */ 11 RGB16, /* 16bpp */
12 RGB24, /* 24bpp */ 12 RGB18, /* 18bpp */
13 SYS8A, /* 24bpp, 8:8:8 */ 13 RGB24, /* 24bpp */
14 SYS8B, /* 18bpp, 8:8:2 */ 14 YUV422, /* 16bpp */
15 SYS8C, /* 18bpp, 2:8:8 */ 15 SYS8A, /* 24bpp, 8:8:8 */
16 SYS8D, /* 16bpp, 8:8 */ 16 SYS8B, /* 18bpp, 8:8:2 */
17 SYS9, /* 18bpp, 9:9 */ 17 SYS8C, /* 18bpp, 2:8:8 */
18 SYS12, /* 24bpp, 12:12 */ 18 SYS8D, /* 16bpp, 8:8 */
19 SYS16A, /* 16bpp */ 19 SYS9, /* 18bpp, 9:9 */
20 SYS16B, /* 18bpp, 16:2 */ 20 SYS12, /* 24bpp, 12:12 */
21 SYS16C, /* 18bpp, 2:16 */ 21 SYS16A, /* 16bpp */
22 SYS18, /* 18bpp */ 22 SYS16B, /* 18bpp, 16:2 */
23 SYS24 };/* 24bpp */ 23 SYS16C, /* 18bpp, 2:16 */
24 SYS18, /* 18bpp */
25 SYS24, /* 24bpp */
26};
24 27
25enum { LCDC_CHAN_DISABLED = 0, 28enum { LCDC_CHAN_DISABLED = 0,
26 LCDC_CHAN_MAINLCD, 29 LCDC_CHAN_MAINLCD,
@@ -52,7 +55,7 @@ struct sh_mobile_lcdc_board_cfg {
52 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 55 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
53 void (*start_transfer)(void *board_data, void *sys_ops_handle, 56 void (*start_transfer)(void *board_data, void *sys_ops_handle,
54 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 57 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
55 void (*display_on)(void *board_data); 58 void (*display_on)(void *board_data, struct fb_info *info);
56 void (*display_off)(void *board_data); 59 void (*display_off)(void *board_data);
57}; 60};
58 61