linux/arch/arm/mach-ux500/cpu-db8500.c
Linus Torvalds 813a95e5b4 arm-soc: soc-specific pinctrl changes
With this, five platforms are moving to the relatively new pinctrl
 subsystem for their pin management, replacing the older soc specific
 in-kernel interfaces with common code.
 
 There is quite a bit of net addition of code for each platform being
 added to the pinctrl subsystem. but the payback comes later when adding
 new boards can be done by only providing new device trees instead.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJPuw1/AAoJEIwa5zzehBx3wbsP/RFCYzMVyz85BNLQuRyY9eO2
 GCRWd0Vvy3fIfypiPdHdhkq6nIU/JnxgsfBbKX9FvWqvxXi96Ojh13KSIhSI1rQ9
 t14VyuwUXaS3leeCyKxhNF1vRscz2iyEGXJqp+XEN4ckf2nrQCpKBiY5Eg9sH6/J
 fvYgSBY9Lf9nFAn+/wqSKIfdvw7H0NXwUdsLvNU0uCwvrSG929bTxx2AnHX00TdJ
 qf4XLhmatMg1uwdUgL/99ZxxgHlj6o55u7S6aRhUWXNXCimV6uEZ1F35ET37b+x3
 YUltBCIaXjFR7iwNHmkkl42d8uyfkBznB555sY5qS3G/uF5Ma1R5I7fv8EIEy+2w
 bVHsva4lj1yFazic6m8yKTET4i8n6OPiKVNqGnDsp2yb6WzOGSliKdr0Jlo1oNG2
 gS69LcDZxCkXrqEq0Ht8uUoCo9TWei+qhJ6ZOJ1Z3+9ZyFq1iRTKgPVxyA5VaHaB
 wwBbqKrohAwuExY8/gkAj6SYqBOF3l/J8QSB2JjXyj4trLC5UMq+l3L4cIWyMRPc
 fil83hV6460CiIBoKcsnV9hDUS0oh74mv52zHo0Xj73qABqZ4dcrpHVayWjtMtpl
 Z+tUpvD1rMQ+E0gdXDrwMrwILVyCDsBvpFKF4avnujDJ4WmyywtKZ+xvnpMd73VZ
 YrI/+XQsMT8ZfVkkj54D
 =HIfz
 -----END PGP SIGNATURE-----

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

Pull arm soc-specific pinctrl changes from Olof Johansson:
 "With this, five platforms are moving to the relatively new pinctrl
  subsystem for their pin management, replacing the older soc specific
  in-kernel interfaces with common code.

  There is quite a bit of net addition of code for each platform being
  added to the pinctrl subsystem.  But the payback comes later when
  adding new boards can be done by only providing new device trees
  instead."

Fix up trivial conflicts in arch/arm/mach-ux500/{Makefile,board-mop500.c}

* tag 'pinctrl' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (61 commits)
  mtd: nand: gpmi: fix compile error caused by pinctrl call
  ARM: PRIMA2: select PINCTRL and PINCTRL_SIRF in Kconfig
  ARM: nomadik: enable PINCTRL_NOMADIK where needed
  ARM: mxs: enable pinctrl support
  video: mxsfb: adopt pinctrl support
  ASoC: mxs-saif: adopt pinctrl support
  i2c: mxs: adopt pinctrl support
  mtd: nand: gpmi: adopt pinctrl support
  mmc: mxs-mmc: adopt pinctrl support
  serial: mxs-auart: adopt pinctrl support
  serial: amba-pl011: adopt pinctrl support
  spi/imx: adopt pinctrl support
  i2c: imx: adopt pinctrl support
  can: flexcan: adopt pinctrl support
  net: fec: adopt pinctrl support
  ARM: ux500: switch MSP to using pinctrl for pins
  ARM: ux500: alter MSP registration to return a device pointer
  ARM: ux500: switch to using pinctrl for uart0
  ARM: ux500: delete custom pin control system
  ARM: ux500: switch over to Nomadik pinctrl driver
  ...
2012-05-22 09:39:42 -07:00

238 lines
6.2 KiB
C

/*
* Copyright (C) 2008-2009 ST-Ericsson SA
*
* Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
*/
#include <linux/types.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/amba/bus.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <asm/mach/map.h>
#include <asm/pmu.h>
#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
#include <mach/usb.h>
#include <mach/db8500-regs.h>
#include "devices-db8500.h"
#include "ste-dma40-db8500.h"
/* minimum static i/o mapping required to boot U8500 platforms */
static struct map_desc u8500_uart_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_UART0_BASE, SZ_4K),
__IO_DEV_DESC(U8500_UART2_BASE, SZ_4K),
};
/* U8500 and U9540 common io_desc */
static struct map_desc u8500_common_io_desc[] __initdata = {
/* SCU base also covers GIC CPU BASE and TWD with its 4K page */
__IO_DEV_DESC(U8500_SCU_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K),
__IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K),
__IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
__IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K),
__IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K),
__IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K),
__IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K),
__IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K),
__IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
};
/* U8500 IO map specific description */
static struct map_desc u8500_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
};
/* U9540 IO map specific description */
static struct map_desc u9540_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K + SZ_8K),
__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K + SZ_8K),
};
void __init u8500_map_io(void)
{
/*
* Map the UARTs early so that the DEBUG_LL stuff continues to work.
*/
iotable_init(u8500_uart_io_desc, ARRAY_SIZE(u8500_uart_io_desc));
ux500_map_io();
iotable_init(u8500_common_io_desc, ARRAY_SIZE(u8500_common_io_desc));
if (cpu_is_u9540())
iotable_init(u9540_io_desc, ARRAY_SIZE(u9540_io_desc));
else
iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
_PRCMU_BASE = __io_address(U8500_PRCMU_BASE);
}
static struct resource db8500_pmu_resources[] = {
[0] = {
.start = IRQ_DB8500_PMU,
.end = IRQ_DB8500_PMU,
.flags = IORESOURCE_IRQ,
},
};
/*
* The PMU IRQ lines of two cores are wired together into a single interrupt.
* Bounce the interrupt to the other core if it's not ours.
*/
static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler)
{
irqreturn_t ret = handler(irq, dev);
int other = !smp_processor_id();
if (ret == IRQ_NONE && cpu_online(other))
irq_set_affinity(irq, cpumask_of(other));
/*
* We should be able to get away with the amount of IRQ_NONEs we give,
* while still having the spurious IRQ detection code kick in if the
* interrupt really starts hitting spuriously.
*/
return ret;
}
static struct arm_pmu_platdata db8500_pmu_platdata = {
.handle_irq = db8500_pmu_handler,
};
static struct platform_device db8500_pmu_device = {
.name = "arm-pmu",
.id = ARM_PMU_DEVICE_CPU,
.num_resources = ARRAY_SIZE(db8500_pmu_resources),
.resource = db8500_pmu_resources,
.dev.platform_data = &db8500_pmu_platdata,
};
static struct platform_device db8500_prcmu_device = {
.name = "db8500-prcmu",
};
static struct platform_device *platform_devs[] __initdata = {
&u8500_dma40_device,
&db8500_pmu_device,
&db8500_prcmu_device,
};
static struct platform_device *of_platform_devs[] __initdata = {
&u8500_dma40_device,
&db8500_pmu_device,
&db8500_prcmu_device,
};
static resource_size_t __initdata db8500_gpio_base[] = {
U8500_GPIOBANK0_BASE,
U8500_GPIOBANK1_BASE,
U8500_GPIOBANK2_BASE,
U8500_GPIOBANK3_BASE,
U8500_GPIOBANK4_BASE,
U8500_GPIOBANK5_BASE,
U8500_GPIOBANK6_BASE,
U8500_GPIOBANK7_BASE,
U8500_GPIOBANK8_BASE,
};
static void __init db8500_add_gpios(struct device *parent)
{
struct nmk_gpio_platform_data pdata = {
.supports_sleepmode = true,
};
dbx500_add_gpios(parent, ARRAY_AND_SIZE(db8500_gpio_base),
IRQ_DB8500_GPIO0, &pdata);
dbx500_add_pinctrl(parent, "pinctrl-db8500");
}
static int usb_db8500_rx_dma_cfg[] = {
DB8500_DMA_DEV38_USB_OTG_IEP_1_9,
DB8500_DMA_DEV37_USB_OTG_IEP_2_10,
DB8500_DMA_DEV36_USB_OTG_IEP_3_11,
DB8500_DMA_DEV19_USB_OTG_IEP_4_12,
DB8500_DMA_DEV18_USB_OTG_IEP_5_13,
DB8500_DMA_DEV17_USB_OTG_IEP_6_14,
DB8500_DMA_DEV16_USB_OTG_IEP_7_15,
DB8500_DMA_DEV39_USB_OTG_IEP_8
};
static int usb_db8500_tx_dma_cfg[] = {
DB8500_DMA_DEV38_USB_OTG_OEP_1_9,
DB8500_DMA_DEV37_USB_OTG_OEP_2_10,
DB8500_DMA_DEV36_USB_OTG_OEP_3_11,
DB8500_DMA_DEV19_USB_OTG_OEP_4_12,
DB8500_DMA_DEV18_USB_OTG_OEP_5_13,
DB8500_DMA_DEV17_USB_OTG_OEP_6_14,
DB8500_DMA_DEV16_USB_OTG_OEP_7_15,
DB8500_DMA_DEV39_USB_OTG_OEP_8
};
static const char *db8500_read_soc_id(void)
{
void __iomem *uid = __io_address(U8500_BB_UID_BASE);
return kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x",
readl((u32 *)uid+1),
readl((u32 *)uid+1), readl((u32 *)uid+2),
readl((u32 *)uid+3), readl((u32 *)uid+4));
}
static struct device * __init db8500_soc_device_init(void)
{
const char *soc_id = db8500_read_soc_id();
return ux500_soc_device_init(soc_id);
}
/*
* This function is called from the board init
*/
struct device * __init u8500_init_devices(void)
{
struct device *parent;
int i;
parent = db8500_soc_device_init();
db8500_add_rtc(parent);
db8500_add_gpios(parent);
db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
platform_device_register_data(parent,
"cpufreq-u8500", -1, NULL, 0);
for (i = 0; i < ARRAY_SIZE(of_platform_devs); i++)
of_platform_devs[i]->dev.parent = parent;
/*
* Devices to be DT:ed:
* u8500_dma40_device = todo
* db8500_pmu_device = todo
* db8500_prcmu_device = todo
*/
platform_add_devices(of_platform_devs, ARRAY_SIZE(of_platform_devs));
return parent;
}