linux/arch/arm/mach-shmobile/setup-r8a7740.c
Linus Torvalds 7ae1c76ee5 arm-soc: pin muxing for sh-mobile
This is another cleanup series, containing the move of the Renesas
 SH-Mobile pin controller code from arch/arm/mach-shmobile over to the
 generic pinctrl subsystem, changing it over to the common interfaces in
 the process.
 
 Based on agreement between Olof, Paul Mundt, Linus Walleij and Simon,
 we're merging this large branch of pinctrl conversion through arm-soc,
 even though it contains the corresponding conversions for arch/sh. Main
 reason for this is tight dependencies (that will now mostly be broken)
 between the arch/sh and mach-shmobile implementations.
 
 There will be more of this in 3.10 to do device-tree bindings, but this
 is the initial conversion.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIVAwUAUSaEl2CrR//JCVInAQI82RAAjpctH6C0WSrbGU0JvK37UARADhIEExBU
 DkmKV7i6yZHMZ11L0u2W5DvO+VPMN/hyIQlHmIJzxXQx/yGysnbshgapRkLKNXPx
 BNOrswOHAuILxxl78b6Wi5DwR0AgLNz2uC8jPFo7FWKjIEIFMV6XTtotc1Je51Cy
 yTetSIuHjWAYYb2cGcYCoN2DLXq6d+RA1vXebyAWOCfZJqtF0DhMAw14gDuxjyMb
 2y5cBZte1ym/mSYtg5JiJGiSnhcl3y5QzUSgIbFJIhnS4DQgztnVXnn5/iAaw0/i
 5f/9brGaVsUYlugZ5zA8NY2UUAiwlilN4W8M42Fe5rOJ6bPrwSbSWkFdwEZpZsMU
 kpV4urrwWVNJAJFCQZx+Cioh1zVxyPdNXtwOwOO73kwf7jSYwr+Kc0K//emw6iOp
 sCUzTHupgL+TWPlYm5SCG8UcM3Cj8TVxmPJ84n/TqhEiejT+lYHMQs6wVNz/xyMX
 +1eX+ZAh+gshY/9tnAMDyYDJTFhNJ33yraKW3a/V/ve/3eaf8yJ8vCKaL1ZqN7jt
 XXbZE26N/Mw8/zazMxfq3NHXpNAiDVVUmMcA8UBUwrRWsVIE/tu4SjmnpFN8BI/j
 L9NsscehKZEZjyZ2CW4NiPx4VsGncStCsMcYkwk4CMHs5k7lgv0+ptRVekDX8COF
 oVodlV4ua3w=
 =U+ce
 -----END PGP SIGNATURE-----

Merge tag 'sh-pinmux' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull sh-mobile pinctrl conversion from Arnd Bergmann:
 "This is another cleanup series, containing the move of the Renesas
  SH-Mobile pin controller code from arch/arm/mach-shmobile over to the
  generic pinctrl subsystem, changing it over to the common interfaces
  in the process.

  Based on agreement between Olof, Paul Mundt, Linus Walleij and Simon,
  we're merging this large branch of pinctrl conversion through arm-soc,
  even though it contains the corresponding conversions for arch/sh.
  Main reason for this is tight dependencies (that will now mostly be
  broken) between the arch/sh and mach-shmobile implementations.

  There will be more of this in 3.10 to do device-tree bindings, but
  this is the initial conversion."

* tag 'sh-pinmux' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (81 commits)
  sh-pfc: sh_pfc_probe() sizeof() fix
  sh-pfc: Move sh_pfc.h from include/linux/ to driver directory
  sh-pfc: Remove pinmux_info definition
  sh: Remove unused sh_pfc_register_info() function
  sh: shx3: pinmux: Use driver-provided pinmux info
  sh: sh7786: pinmux: Use driver-provided pinmux info
  sh: sh7785: pinmux: Use driver-provided pinmux info
  sh: sh7757: pinmux: Use driver-provided pinmux info
  sh: sh7734: pinmux: Use driver-provided pinmux info
  sh: sh7724: pinmux: Use driver-provided pinmux info
  sh: sh7723: pinmux: Use driver-provided pinmux info
  sh: sh7722: pinmux: Use driver-provided pinmux info
  sh: sh7720: pinmux: Use driver-provided pinmux info
  sh: sh7269: pinmux: Use driver-provided pinmux info
  sh: sh7264: pinmux: Use driver-provided pinmux info
  sh: sh7203: pinmux: Use driver-provided pinmux info
  ARM: shmobile: sh73a0: Use driver-provided pinmux info
  ARM: shmobile: sh7372: Use driver-provided pinmux info
  ARM: shmobile: r8a7779: Use driver-provided pinmux info
  ARM: shmobile: r8a7740: Use driver-provided pinmux info
  ...
2013-02-21 15:00:16 -08:00

788 lines
18 KiB
C

/*
* R8A7740 processor support
*
* Copyright (C) 2011 Renesas Solutions Corp.
* Copyright (C) 2011 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/serial_sci.h>
#include <linux/sh_dma.h>
#include <linux/sh_timer.h>
#include <linux/dma-mapping.h>
#include <mach/dma-register.h>
#include <mach/r8a7740.h>
#include <mach/pm-rmobile.h>
#include <mach/common.h>
#include <mach/irqs.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
static struct map_desc r8a7740_io_desc[] __initdata = {
/*
* for CPGA/INTC/PFC
* 0xe6000000-0xefffffff -> 0xe6000000-0xefffffff
*/
{
.virtual = 0xe6000000,
.pfn = __phys_to_pfn(0xe6000000),
.length = 160 << 20,
.type = MT_DEVICE_NONSHARED
},
#ifdef CONFIG_CACHE_L2X0
/*
* for l2x0_init()
* 0xf0100000-0xf0101000 -> 0xf0002000-0xf0003000
*/
{
.virtual = 0xf0002000,
.pfn = __phys_to_pfn(0xf0100000),
.length = PAGE_SIZE,
.type = MT_DEVICE_NONSHARED
},
#endif
};
void __init r8a7740_map_io(void)
{
iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc));
}
/* PFC */
static struct resource r8a7740_pfc_resources[] = {
[0] = {
.start = 0xe6050000,
.end = 0xe6057fff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 0xe605800c,
.end = 0xe605802b,
.flags = IORESOURCE_MEM,
}
};
static struct platform_device r8a7740_pfc_device = {
.name = "pfc-r8a7740",
.id = -1,
.resource = r8a7740_pfc_resources,
.num_resources = ARRAY_SIZE(r8a7740_pfc_resources),
};
void __init r8a7740_pinmux_init(void)
{
platform_device_register(&r8a7740_pfc_device);
}
/* SCIFA0 */
static struct plat_sci_port scif0_platform_data = {
.mapbase = 0xe6c40000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0c00)),
};
static struct platform_device scif0_device = {
.name = "sh-sci",
.id = 0,
.dev = {
.platform_data = &scif0_platform_data,
},
};
/* SCIFA1 */
static struct plat_sci_port scif1_platform_data = {
.mapbase = 0xe6c50000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0c20)),
};
static struct platform_device scif1_device = {
.name = "sh-sci",
.id = 1,
.dev = {
.platform_data = &scif1_platform_data,
},
};
/* SCIFA2 */
static struct plat_sci_port scif2_platform_data = {
.mapbase = 0xe6c60000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0c40)),
};
static struct platform_device scif2_device = {
.name = "sh-sci",
.id = 2,
.dev = {
.platform_data = &scif2_platform_data,
},
};
/* SCIFA3 */
static struct plat_sci_port scif3_platform_data = {
.mapbase = 0xe6c70000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0c60)),
};
static struct platform_device scif3_device = {
.name = "sh-sci",
.id = 3,
.dev = {
.platform_data = &scif3_platform_data,
},
};
/* SCIFA4 */
static struct plat_sci_port scif4_platform_data = {
.mapbase = 0xe6c80000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0d20)),
};
static struct platform_device scif4_device = {
.name = "sh-sci",
.id = 4,
.dev = {
.platform_data = &scif4_platform_data,
},
};
/* SCIFA5 */
static struct plat_sci_port scif5_platform_data = {
.mapbase = 0xe6cb0000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0d40)),
};
static struct platform_device scif5_device = {
.name = "sh-sci",
.id = 5,
.dev = {
.platform_data = &scif5_platform_data,
},
};
/* SCIFA6 */
static struct plat_sci_port scif6_platform_data = {
.mapbase = 0xe6cc0000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x04c0)),
};
static struct platform_device scif6_device = {
.name = "sh-sci",
.id = 6,
.dev = {
.platform_data = &scif6_platform_data,
},
};
/* SCIFA7 */
static struct plat_sci_port scif7_platform_data = {
.mapbase = 0xe6cd0000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x04e0)),
};
static struct platform_device scif7_device = {
.name = "sh-sci",
.id = 7,
.dev = {
.platform_data = &scif7_platform_data,
},
};
/* SCIFB */
static struct plat_sci_port scifb_platform_data = {
.mapbase = 0xe6c30000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFB,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0d60)),
};
static struct platform_device scifb_device = {
.name = "sh-sci",
.id = 8,
.dev = {
.platform_data = &scifb_platform_data,
},
};
/* CMT */
static struct sh_timer_config cmt10_platform_data = {
.name = "CMT10",
.channel_offset = 0x10,
.timer_bit = 0,
.clockevent_rating = 125,
.clocksource_rating = 125,
};
static struct resource cmt10_resources[] = {
[0] = {
.name = "CMT10",
.start = 0xe6138010,
.end = 0xe613801b,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = evt2irq(0x0b00),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device cmt10_device = {
.name = "sh_cmt",
.id = 10,
.dev = {
.platform_data = &cmt10_platform_data,
},
.resource = cmt10_resources,
.num_resources = ARRAY_SIZE(cmt10_resources),
};
static struct platform_device *r8a7740_early_devices[] __initdata = {
&scif0_device,
&scif1_device,
&scif2_device,
&scif3_device,
&scif4_device,
&scif5_device,
&scif6_device,
&scif7_device,
&scifb_device,
&cmt10_device,
};
/* DMA */
static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
{
.slave_id = SHDMA_SLAVE_SDHI0_TX,
.addr = 0xe6850030,
.chcr = CHCR_TX(XMIT_SZ_16BIT),
.mid_rid = 0xc1,
}, {
.slave_id = SHDMA_SLAVE_SDHI0_RX,
.addr = 0xe6850030,
.chcr = CHCR_RX(XMIT_SZ_16BIT),
.mid_rid = 0xc2,
}, {
.slave_id = SHDMA_SLAVE_SDHI1_TX,
.addr = 0xe6860030,
.chcr = CHCR_TX(XMIT_SZ_16BIT),
.mid_rid = 0xc9,
}, {
.slave_id = SHDMA_SLAVE_SDHI1_RX,
.addr = 0xe6860030,
.chcr = CHCR_RX(XMIT_SZ_16BIT),
.mid_rid = 0xca,
}, {
.slave_id = SHDMA_SLAVE_SDHI2_TX,
.addr = 0xe6870030,
.chcr = CHCR_TX(XMIT_SZ_16BIT),
.mid_rid = 0xcd,
}, {
.slave_id = SHDMA_SLAVE_SDHI2_RX,
.addr = 0xe6870030,
.chcr = CHCR_RX(XMIT_SZ_16BIT),
.mid_rid = 0xce,
}, {
.slave_id = SHDMA_SLAVE_FSIA_TX,
.addr = 0xfe1f0024,
.chcr = CHCR_TX(XMIT_SZ_32BIT),
.mid_rid = 0xb1,
}, {
.slave_id = SHDMA_SLAVE_FSIA_RX,
.addr = 0xfe1f0020,
.chcr = CHCR_RX(XMIT_SZ_32BIT),
.mid_rid = 0xb2,
}, {
.slave_id = SHDMA_SLAVE_FSIB_TX,
.addr = 0xfe1f0064,
.chcr = CHCR_TX(XMIT_SZ_32BIT),
.mid_rid = 0xb5,
},
};
#define DMA_CHANNEL(a, b, c) \
{ \
.offset = a, \
.dmars = b, \
.dmars_bit = c, \
.chclr_offset = (0x220 - 0x20) + a \
}
static const struct sh_dmae_channel r8a7740_dmae_channels[] = {
DMA_CHANNEL(0x00, 0, 0),
DMA_CHANNEL(0x10, 0, 8),
DMA_CHANNEL(0x20, 4, 0),
DMA_CHANNEL(0x30, 4, 8),
DMA_CHANNEL(0x50, 8, 0),
DMA_CHANNEL(0x60, 8, 8),
};
static struct sh_dmae_pdata dma_platform_data = {
.slave = r8a7740_dmae_slaves,
.slave_num = ARRAY_SIZE(r8a7740_dmae_slaves),
.channel = r8a7740_dmae_channels,
.channel_num = ARRAY_SIZE(r8a7740_dmae_channels),
.ts_low_shift = TS_LOW_SHIFT,
.ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT,
.ts_high_shift = TS_HI_SHIFT,
.ts_high_mask = TS_HI_BIT << TS_HI_SHIFT,
.ts_shift = dma_ts_shift,
.ts_shift_num = ARRAY_SIZE(dma_ts_shift),
.dmaor_init = DMAOR_DME,
.chclr_present = 1,
};
/* Resource order important! */
static struct resource r8a7740_dmae0_resources[] = {
{
/* Channel registers and DMAOR */
.start = 0xfe008020,
.end = 0xfe00828f,
.flags = IORESOURCE_MEM,
},
{
/* DMARSx */
.start = 0xfe009000,
.end = 0xfe00900b,
.flags = IORESOURCE_MEM,
},
{
.name = "error_irq",
.start = evt2irq(0x20c0),
.end = evt2irq(0x20c0),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 0-5 */
.start = evt2irq(0x2000),
.end = evt2irq(0x20a0),
.flags = IORESOURCE_IRQ,
},
};
/* Resource order important! */
static struct resource r8a7740_dmae1_resources[] = {
{
/* Channel registers and DMAOR */
.start = 0xfe018020,
.end = 0xfe01828f,
.flags = IORESOURCE_MEM,
},
{
/* DMARSx */
.start = 0xfe019000,
.end = 0xfe01900b,
.flags = IORESOURCE_MEM,
},
{
.name = "error_irq",
.start = evt2irq(0x21c0),
.end = evt2irq(0x21c0),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 0-5 */
.start = evt2irq(0x2100),
.end = evt2irq(0x21a0),
.flags = IORESOURCE_IRQ,
},
};
/* Resource order important! */
static struct resource r8a7740_dmae2_resources[] = {
{
/* Channel registers and DMAOR */
.start = 0xfe028020,
.end = 0xfe02828f,
.flags = IORESOURCE_MEM,
},
{
/* DMARSx */
.start = 0xfe029000,
.end = 0xfe02900b,
.flags = IORESOURCE_MEM,
},
{
.name = "error_irq",
.start = evt2irq(0x22c0),
.end = evt2irq(0x22c0),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 0-5 */
.start = evt2irq(0x2200),
.end = evt2irq(0x22a0),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device dma0_device = {
.name = "sh-dma-engine",
.id = 0,
.resource = r8a7740_dmae0_resources,
.num_resources = ARRAY_SIZE(r8a7740_dmae0_resources),
.dev = {
.platform_data = &dma_platform_data,
},
};
static struct platform_device dma1_device = {
.name = "sh-dma-engine",
.id = 1,
.resource = r8a7740_dmae1_resources,
.num_resources = ARRAY_SIZE(r8a7740_dmae1_resources),
.dev = {
.platform_data = &dma_platform_data,
},
};
static struct platform_device dma2_device = {
.name = "sh-dma-engine",
.id = 2,
.resource = r8a7740_dmae2_resources,
.num_resources = ARRAY_SIZE(r8a7740_dmae2_resources),
.dev = {
.platform_data = &dma_platform_data,
},
};
/* USB-DMAC */
static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = {
{
.offset = 0,
}, {
.offset = 0x20,
},
};
static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = {
{
.slave_id = SHDMA_SLAVE_USBHS_TX,
.chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
}, {
.slave_id = SHDMA_SLAVE_USBHS_RX,
.chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
},
};
static struct sh_dmae_pdata usb_dma_platform_data = {
.slave = r8a7740_usb_dma_slaves,
.slave_num = ARRAY_SIZE(r8a7740_usb_dma_slaves),
.channel = r8a7740_usb_dma_channels,
.channel_num = ARRAY_SIZE(r8a7740_usb_dma_channels),
.ts_low_shift = USBTS_LOW_SHIFT,
.ts_low_mask = USBTS_LOW_BIT << USBTS_LOW_SHIFT,
.ts_high_shift = USBTS_HI_SHIFT,
.ts_high_mask = USBTS_HI_BIT << USBTS_HI_SHIFT,
.ts_shift = dma_usbts_shift,
.ts_shift_num = ARRAY_SIZE(dma_usbts_shift),
.dmaor_init = DMAOR_DME,
.chcr_offset = 0x14,
.chcr_ie_bit = 1 << 5,
.dmaor_is_32bit = 1,
.needs_tend_set = 1,
.no_dmars = 1,
.slave_only = 1,
};
static struct resource r8a7740_usb_dma_resources[] = {
{
/* Channel registers and DMAOR */
.start = 0xe68a0020,
.end = 0xe68a0064 - 1,
.flags = IORESOURCE_MEM,
},
{
/* VCR/SWR/DMICR */
.start = 0xe68a0000,
.end = 0xe68a0014 - 1,
.flags = IORESOURCE_MEM,
},
{
/* IRQ for channels */
.start = evt2irq(0x0a00),
.end = evt2irq(0x0a00),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device usb_dma_device = {
.name = "sh-dma-engine",
.id = 3,
.resource = r8a7740_usb_dma_resources,
.num_resources = ARRAY_SIZE(r8a7740_usb_dma_resources),
.dev = {
.platform_data = &usb_dma_platform_data,
},
};
/* I2C */
static struct resource i2c0_resources[] = {
[0] = {
.name = "IIC0",
.start = 0xfff20000,
.end = 0xfff20425 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = intcs_evt2irq(0xe00),
.end = intcs_evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
static struct resource i2c1_resources[] = {
[0] = {
.name = "IIC1",
.start = 0xe6c20000,
.end = 0xe6c20425 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = evt2irq(0x780), /* IIC1_ALI1 */
.end = evt2irq(0x7e0), /* IIC1_DTEI1 */
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device i2c0_device = {
.name = "i2c-sh_mobile",
.id = 0,
.resource = i2c0_resources,
.num_resources = ARRAY_SIZE(i2c0_resources),
};
static struct platform_device i2c1_device = {
.name = "i2c-sh_mobile",
.id = 1,
.resource = i2c1_resources,
.num_resources = ARRAY_SIZE(i2c1_resources),
};
static struct resource pmu_resources[] = {
[0] = {
.start = evt2irq(0x19a0),
.end = evt2irq(0x19a0),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device pmu_device = {
.name = "arm-pmu",
.id = -1,
.num_resources = ARRAY_SIZE(pmu_resources),
.resource = pmu_resources,
};
static struct platform_device *r8a7740_late_devices[] __initdata = {
&i2c0_device,
&i2c1_device,
&dma0_device,
&dma1_device,
&dma2_device,
&usb_dma_device,
&pmu_device,
};
/*
* r8a7740 chip has lasting errata on MERAM buffer.
* this is work-around for it.
* see
* "Media RAM (MERAM)" on r8a7740 documentation
*/
#define MEBUFCNTR 0xFE950098
void r8a7740_meram_workaround(void)
{
void __iomem *reg;
reg = ioremap_nocache(MEBUFCNTR, 4);
if (reg) {
iowrite32(0x01600164, reg);
iounmap(reg);
}
}
#define ICCR 0x0004
#define ICSTART 0x0070
#define i2c_read(reg, offset) ioread8(reg + offset)
#define i2c_write(reg, offset, data) iowrite8(data, reg + offset)
/*
* r8a7740 chip has lasting errata on I2C I/O pad reset.
* this is work-around for it.
*/
static void r8a7740_i2c_workaround(struct platform_device *pdev)
{
struct resource *res;
void __iomem *reg;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (unlikely(!res)) {
pr_err("r8a7740 i2c workaround fail (cannot find resource)\n");
return;
}
reg = ioremap(res->start, resource_size(res));
if (unlikely(!reg)) {
pr_err("r8a7740 i2c workaround fail (cannot map IO)\n");
return;
}
i2c_write(reg, ICCR, i2c_read(reg, ICCR) | 0x80);
i2c_read(reg, ICCR); /* dummy read */
i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10);
i2c_read(reg, ICSTART); /* dummy read */
udelay(10);
i2c_write(reg, ICCR, 0x01);
i2c_write(reg, ICSTART, 0x00);
udelay(10);
i2c_write(reg, ICCR, 0x10);
udelay(10);
i2c_write(reg, ICCR, 0x00);
udelay(10);
i2c_write(reg, ICCR, 0x10);
udelay(10);
iounmap(reg);
}
void __init r8a7740_add_standard_devices(void)
{
/* I2C work-around */
r8a7740_i2c_workaround(&i2c0_device);
r8a7740_i2c_workaround(&i2c1_device);
r8a7740_init_pm_domains();
/* add devices */
platform_add_devices(r8a7740_early_devices,
ARRAY_SIZE(r8a7740_early_devices));
platform_add_devices(r8a7740_late_devices,
ARRAY_SIZE(r8a7740_late_devices));
/* add devices to PM domain */
rmobile_add_device_to_domain("A3SP", &scif0_device);
rmobile_add_device_to_domain("A3SP", &scif1_device);
rmobile_add_device_to_domain("A3SP", &scif2_device);
rmobile_add_device_to_domain("A3SP", &scif3_device);
rmobile_add_device_to_domain("A3SP", &scif4_device);
rmobile_add_device_to_domain("A3SP", &scif5_device);
rmobile_add_device_to_domain("A3SP", &scif6_device);
rmobile_add_device_to_domain("A3SP", &scif7_device);
rmobile_add_device_to_domain("A3SP", &scifb_device);
rmobile_add_device_to_domain("A3SP", &i2c1_device);
}
void __init r8a7740_add_early_devices(void)
{
early_platform_add_devices(r8a7740_early_devices,
ARRAY_SIZE(r8a7740_early_devices));
/* setup early console here as well */
shmobile_setup_console();
}
#ifdef CONFIG_USE_OF
void __init r8a7740_add_early_devices_dt(void)
{
shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
early_platform_add_devices(r8a7740_early_devices,
ARRAY_SIZE(r8a7740_early_devices));
/* setup early console here as well */
shmobile_setup_console();
}
static const struct of_dev_auxdata r8a7740_auxdata_lookup[] __initconst = {
{ }
};
void __init r8a7740_add_standard_devices_dt(void)
{
/* clocks are setup late during boot in the case of DT */
r8a7740_clock_init(0);
platform_add_devices(r8a7740_early_devices,
ARRAY_SIZE(r8a7740_early_devices));
of_platform_populate(NULL, of_default_bus_match_table,
r8a7740_auxdata_lookup, NULL);
}
static const char *r8a7740_boards_compat_dt[] __initdata = {
"renesas,r8a7740",
NULL,
};
DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)")
.map_io = r8a7740_map_io,
.init_early = r8a7740_add_early_devices_dt,
.init_irq = r8a7740_init_irq,
.handle_irq = shmobile_handle_irq_intc,
.init_machine = r8a7740_add_standard_devices_dt,
.init_time = shmobile_timer_init,
.dt_compat = r8a7740_boards_compat_dt,
MACHINE_END
#endif /* CONFIG_USE_OF */