forked from Minki/linux
389eda15e0
Support clk in gpio driver. There's no gpio clock in PXA25x and PXA27x. So use dummy clk instead. And move the gpio edge initialization into gpio driver for arch-mmp. Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
236 lines
6.6 KiB
C
236 lines
6.6 KiB
C
/*
|
|
* linux/arch/arm/mach-mmp/mmp2.c
|
|
*
|
|
* code name MMP2
|
|
*
|
|
* Copyright (C) 2009 Marvell International Ltd.
|
|
*
|
|
* 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/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <asm/hardware/cache-tauros2.h>
|
|
|
|
#include <asm/mach/time.h>
|
|
#include <mach/addr-map.h>
|
|
#include <mach/regs-apbc.h>
|
|
#include <mach/regs-apmu.h>
|
|
#include <mach/cputype.h>
|
|
#include <mach/irqs.h>
|
|
#include <mach/dma.h>
|
|
#include <mach/mfp.h>
|
|
#include <mach/devices.h>
|
|
#include <mach/mmp2.h>
|
|
|
|
#include "common.h"
|
|
#include "clock.h"
|
|
|
|
#define MFPR_VIRT_BASE (APB_VIRT_BASE + 0x1e000)
|
|
|
|
static struct mfp_addr_map mmp2_addr_map[] __initdata = {
|
|
|
|
MFP_ADDR_X(GPIO0, GPIO58, 0x54),
|
|
MFP_ADDR_X(GPIO59, GPIO73, 0x280),
|
|
MFP_ADDR_X(GPIO74, GPIO101, 0x170),
|
|
|
|
MFP_ADDR(GPIO102, 0x0),
|
|
MFP_ADDR(GPIO103, 0x4),
|
|
MFP_ADDR(GPIO104, 0x1fc),
|
|
MFP_ADDR(GPIO105, 0x1f8),
|
|
MFP_ADDR(GPIO106, 0x1f4),
|
|
MFP_ADDR(GPIO107, 0x1f0),
|
|
MFP_ADDR(GPIO108, 0x21c),
|
|
MFP_ADDR(GPIO109, 0x218),
|
|
MFP_ADDR(GPIO110, 0x214),
|
|
MFP_ADDR(GPIO111, 0x200),
|
|
MFP_ADDR(GPIO112, 0x244),
|
|
MFP_ADDR(GPIO113, 0x25c),
|
|
MFP_ADDR(GPIO114, 0x164),
|
|
MFP_ADDR_X(GPIO115, GPIO122, 0x260),
|
|
|
|
MFP_ADDR(GPIO123, 0x148),
|
|
MFP_ADDR_X(GPIO124, GPIO141, 0xc),
|
|
|
|
MFP_ADDR(GPIO142, 0x8),
|
|
MFP_ADDR_X(GPIO143, GPIO151, 0x220),
|
|
MFP_ADDR_X(GPIO152, GPIO153, 0x248),
|
|
MFP_ADDR_X(GPIO154, GPIO155, 0x254),
|
|
MFP_ADDR_X(GPIO156, GPIO159, 0x14c),
|
|
|
|
MFP_ADDR(GPIO160, 0x250),
|
|
MFP_ADDR(GPIO161, 0x210),
|
|
MFP_ADDR(GPIO162, 0x20c),
|
|
MFP_ADDR(GPIO163, 0x208),
|
|
MFP_ADDR(GPIO164, 0x204),
|
|
MFP_ADDR(GPIO165, 0x1ec),
|
|
MFP_ADDR(GPIO166, 0x1e8),
|
|
MFP_ADDR(GPIO167, 0x1e4),
|
|
MFP_ADDR(GPIO168, 0x1e0),
|
|
|
|
MFP_ADDR_X(TWSI1_SCL, TWSI1_SDA, 0x140),
|
|
MFP_ADDR_X(TWSI4_SCL, TWSI4_SDA, 0x2bc),
|
|
|
|
MFP_ADDR(PMIC_INT, 0x2c4),
|
|
MFP_ADDR(CLK_REQ, 0x160),
|
|
|
|
MFP_ADDR_END,
|
|
};
|
|
|
|
void mmp2_clear_pmic_int(void)
|
|
{
|
|
void __iomem *mfpr_pmic;
|
|
unsigned long data;
|
|
|
|
mfpr_pmic = APB_VIRT_BASE + 0x1e000 + 0x2c4;
|
|
data = __raw_readl(mfpr_pmic);
|
|
__raw_writel(data | (1 << 6), mfpr_pmic);
|
|
__raw_writel(data, mfpr_pmic);
|
|
}
|
|
|
|
void __init mmp2_init_irq(void)
|
|
{
|
|
mmp2_init_icu();
|
|
}
|
|
|
|
static void sdhc_clk_enable(struct clk *clk)
|
|
{
|
|
uint32_t clk_rst;
|
|
|
|
clk_rst = __raw_readl(clk->clk_rst);
|
|
clk_rst |= clk->enable_val;
|
|
__raw_writel(clk_rst, clk->clk_rst);
|
|
}
|
|
|
|
static void sdhc_clk_disable(struct clk *clk)
|
|
{
|
|
uint32_t clk_rst;
|
|
|
|
clk_rst = __raw_readl(clk->clk_rst);
|
|
clk_rst &= ~clk->enable_val;
|
|
__raw_writel(clk_rst, clk->clk_rst);
|
|
}
|
|
|
|
struct clkops sdhc_clk_ops = {
|
|
.enable = sdhc_clk_enable,
|
|
.disable = sdhc_clk_disable,
|
|
};
|
|
|
|
/* APB peripheral clocks */
|
|
static APBC_CLK(uart1, MMP2_UART1, 1, 26000000);
|
|
static APBC_CLK(uart2, MMP2_UART2, 1, 26000000);
|
|
static APBC_CLK(uart3, MMP2_UART3, 1, 26000000);
|
|
static APBC_CLK(uart4, MMP2_UART4, 1, 26000000);
|
|
static APBC_CLK(twsi1, MMP2_TWSI1, 0, 26000000);
|
|
static APBC_CLK(twsi2, MMP2_TWSI2, 0, 26000000);
|
|
static APBC_CLK(twsi3, MMP2_TWSI3, 0, 26000000);
|
|
static APBC_CLK(twsi4, MMP2_TWSI4, 0, 26000000);
|
|
static APBC_CLK(twsi5, MMP2_TWSI5, 0, 26000000);
|
|
static APBC_CLK(twsi6, MMP2_TWSI6, 0, 26000000);
|
|
static APBC_CLK(gpio, MMP2_GPIO, 0, 26000000);
|
|
|
|
static APMU_CLK(nand, NAND, 0xbf, 100000000);
|
|
static APMU_CLK_OPS(sdh0, SDH0, 0x1b, 200000000, &sdhc_clk_ops);
|
|
static APMU_CLK_OPS(sdh1, SDH1, 0x1b, 200000000, &sdhc_clk_ops);
|
|
static APMU_CLK_OPS(sdh2, SDH2, 0x1b, 200000000, &sdhc_clk_ops);
|
|
static APMU_CLK_OPS(sdh3, SDH3, 0x1b, 200000000, &sdhc_clk_ops);
|
|
|
|
static struct clk_lookup mmp2_clkregs[] = {
|
|
INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
|
|
INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
|
|
INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
|
|
INIT_CLKREG(&clk_uart4, "pxa2xx-uart.3", NULL),
|
|
INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.0", NULL),
|
|
INIT_CLKREG(&clk_twsi2, "pxa2xx-i2c.1", NULL),
|
|
INIT_CLKREG(&clk_twsi3, "pxa2xx-i2c.2", NULL),
|
|
INIT_CLKREG(&clk_twsi4, "pxa2xx-i2c.3", NULL),
|
|
INIT_CLKREG(&clk_twsi5, "pxa2xx-i2c.4", NULL),
|
|
INIT_CLKREG(&clk_twsi6, "pxa2xx-i2c.5", NULL),
|
|
INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
|
|
INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
|
|
INIT_CLKREG(&clk_sdh0, "sdhci-pxav3.0", "PXA-SDHCLK"),
|
|
INIT_CLKREG(&clk_sdh1, "sdhci-pxav3.1", "PXA-SDHCLK"),
|
|
INIT_CLKREG(&clk_sdh2, "sdhci-pxav3.2", "PXA-SDHCLK"),
|
|
INIT_CLKREG(&clk_sdh3, "sdhci-pxav3.3", "PXA-SDHCLK"),
|
|
};
|
|
|
|
static int __init mmp2_init(void)
|
|
{
|
|
if (cpu_is_mmp2()) {
|
|
#ifdef CONFIG_CACHE_TAUROS2
|
|
tauros2_init();
|
|
#endif
|
|
mfp_init_base(MFPR_VIRT_BASE);
|
|
mfp_init_addr(mmp2_addr_map);
|
|
pxa_init_dma(IRQ_MMP2_DMA_RIQ, 16);
|
|
clkdev_add_table(ARRAY_AND_SIZE(mmp2_clkregs));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
postcore_initcall(mmp2_init);
|
|
|
|
static void __init mmp2_timer_init(void)
|
|
{
|
|
unsigned long clk_rst;
|
|
|
|
__raw_writel(APBC_APBCLK | APBC_RST, APBC_MMP2_TIMERS);
|
|
|
|
/*
|
|
* enable bus/functional clock, enable 6.5MHz (divider 4),
|
|
* release reset
|
|
*/
|
|
clk_rst = APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(1);
|
|
__raw_writel(clk_rst, APBC_MMP2_TIMERS);
|
|
|
|
timer_init(IRQ_MMP2_TIMER1);
|
|
}
|
|
|
|
struct sys_timer mmp2_timer = {
|
|
.init = mmp2_timer_init,
|
|
};
|
|
|
|
/* on-chip devices */
|
|
MMP2_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4030000, 0x30, 4, 5);
|
|
MMP2_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4017000, 0x30, 20, 21);
|
|
MMP2_DEVICE(uart3, "pxa2xx-uart", 2, UART3, 0xd4018000, 0x30, 22, 23);
|
|
MMP2_DEVICE(uart4, "pxa2xx-uart", 3, UART4, 0xd4016000, 0x30, 18, 19);
|
|
MMP2_DEVICE(twsi1, "pxa2xx-i2c", 0, TWSI1, 0xd4011000, 0x70);
|
|
MMP2_DEVICE(twsi2, "pxa2xx-i2c", 1, TWSI2, 0xd4031000, 0x70);
|
|
MMP2_DEVICE(twsi3, "pxa2xx-i2c", 2, TWSI3, 0xd4032000, 0x70);
|
|
MMP2_DEVICE(twsi4, "pxa2xx-i2c", 3, TWSI4, 0xd4033000, 0x70);
|
|
MMP2_DEVICE(twsi5, "pxa2xx-i2c", 4, TWSI5, 0xd4033800, 0x70);
|
|
MMP2_DEVICE(twsi6, "pxa2xx-i2c", 5, TWSI6, 0xd4034000, 0x70);
|
|
MMP2_DEVICE(nand, "pxa3xx-nand", -1, NAND, 0xd4283000, 0x100, 28, 29);
|
|
MMP2_DEVICE(sdh0, "sdhci-pxav3", 0, MMC, 0xd4280000, 0x120);
|
|
MMP2_DEVICE(sdh1, "sdhci-pxav3", 1, MMC2, 0xd4280800, 0x120);
|
|
MMP2_DEVICE(sdh2, "sdhci-pxav3", 2, MMC3, 0xd4281000, 0x120);
|
|
MMP2_DEVICE(sdh3, "sdhci-pxav3", 3, MMC4, 0xd4281800, 0x120);
|
|
MMP2_DEVICE(asram, "asram", -1, NONE, 0xe0000000, 0x4000);
|
|
/* 0xd1000000 ~ 0xd101ffff is reserved for secure processor */
|
|
MMP2_DEVICE(isram, "isram", -1, NONE, 0xd1020000, 0x18000);
|
|
|
|
struct resource mmp2_resource_gpio[] = {
|
|
{
|
|
.start = 0xd4019000,
|
|
.end = 0xd4019fff,
|
|
.flags = IORESOURCE_MEM,
|
|
}, {
|
|
.start = IRQ_MMP2_GPIO,
|
|
.end = IRQ_MMP2_GPIO,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
struct platform_device mmp2_device_gpio = {
|
|
.name = "pxa-gpio",
|
|
.id = -1,
|
|
.num_resources = ARRAY_SIZE(mmp2_resource_gpio),
|
|
.resource = mmp2_resource_gpio,
|
|
};
|