forked from luck/tmp_suning_uos_patched
Merge branch 'for-rmk-devel-stable' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson into devel-stable
This commit is contained in:
commit
4c4070a309
@ -3,7 +3,7 @@
|
||||
* arch/arm/mach-u300/core.c
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2007-2010 ST-Ericsson AB
|
||||
* Copyright (C) 2007-2010 ST-Ericsson SA
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
* Core platform support, IRQ handling and device definitions.
|
||||
* Author: Linus Walleij <linus.walleij@stericsson.com>
|
||||
@ -16,7 +16,9 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/termios.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/serial.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/clk.h>
|
||||
@ -96,10 +98,20 @@ void __init u300_map_io(void)
|
||||
* Declaration of devices found on the U300 board and
|
||||
* their respective memory locations.
|
||||
*/
|
||||
|
||||
static struct amba_pl011_data uart0_plat_data = {
|
||||
#ifdef CONFIG_COH901318
|
||||
.dma_filter = coh901318_filter_id,
|
||||
.dma_rx_param = (void *) U300_DMA_UART0_RX,
|
||||
.dma_tx_param = (void *) U300_DMA_UART0_TX,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct amba_device uart0_device = {
|
||||
.dev = {
|
||||
.coherent_dma_mask = ~0,
|
||||
.init_name = "uart0", /* Slow device at 0x3000 offset */
|
||||
.platform_data = NULL,
|
||||
.platform_data = &uart0_plat_data,
|
||||
},
|
||||
.res = {
|
||||
.start = U300_UART0_BASE,
|
||||
@ -111,10 +123,19 @@ static struct amba_device uart0_device = {
|
||||
|
||||
/* The U335 have an additional UART1 on the APP CPU */
|
||||
#ifdef CONFIG_MACH_U300_BS335
|
||||
static struct amba_pl011_data uart1_plat_data = {
|
||||
#ifdef CONFIG_COH901318
|
||||
.dma_filter = coh901318_filter_id,
|
||||
.dma_rx_param = (void *) U300_DMA_UART1_RX,
|
||||
.dma_tx_param = (void *) U300_DMA_UART1_TX,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct amba_device uart1_device = {
|
||||
.dev = {
|
||||
.coherent_dma_mask = ~0,
|
||||
.init_name = "uart1", /* Fast device at 0x7000 offset */
|
||||
.platform_data = NULL,
|
||||
.platform_data = &uart1_plat_data,
|
||||
},
|
||||
.res = {
|
||||
.start = U300_UART1_BASE,
|
||||
@ -960,42 +981,37 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
|
||||
.priority_high = 0,
|
||||
.dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x220,
|
||||
},
|
||||
/*
|
||||
* Don't set up device address, burst count or size of src
|
||||
* or dst bus for this peripheral - handled by PrimeCell
|
||||
* DMA extension.
|
||||
*/
|
||||
{
|
||||
.number = U300_DMA_MMCSD_RX_TX,
|
||||
.name = "MMCSD RX TX",
|
||||
.priority_high = 0,
|
||||
.dev_addr = U300_MMCSD_BASE + 0x080,
|
||||
.param.config = COH901318_CX_CFG_CH_DISABLE |
|
||||
COH901318_CX_CFG_LCR_DISABLE |
|
||||
COH901318_CX_CFG_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CFG_BE_IRQ_ENABLE,
|
||||
.param.ctrl_lli_chained = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
|
||||
COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
|
||||
COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_DISABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
.param.ctrl_lli = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
|
||||
COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
|
||||
COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_DISABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
.param.ctrl_lli_last = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
|
||||
COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
|
||||
COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_DISABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
@ -1014,15 +1030,76 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
|
||||
.name = "MSPRO RX",
|
||||
.priority_high = 0,
|
||||
},
|
||||
/*
|
||||
* Don't set up device address, burst count or size of src
|
||||
* or dst bus for this peripheral - handled by PrimeCell
|
||||
* DMA extension.
|
||||
*/
|
||||
{
|
||||
.number = U300_DMA_UART0_TX,
|
||||
.name = "UART0 TX",
|
||||
.priority_high = 0,
|
||||
.param.config = COH901318_CX_CFG_CH_DISABLE |
|
||||
COH901318_CX_CFG_LCR_DISABLE |
|
||||
COH901318_CX_CFG_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CFG_BE_IRQ_ENABLE,
|
||||
.param.ctrl_lli_chained = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_DISABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
.param.ctrl_lli = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
.param.ctrl_lli_last = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
},
|
||||
{
|
||||
.number = U300_DMA_UART0_RX,
|
||||
.name = "UART0 RX",
|
||||
.priority_high = 0,
|
||||
.param.config = COH901318_CX_CFG_CH_DISABLE |
|
||||
COH901318_CX_CFG_LCR_DISABLE |
|
||||
COH901318_CX_CFG_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CFG_BE_IRQ_ENABLE,
|
||||
.param.ctrl_lli_chained = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_DISABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
.param.ctrl_lli = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
.param.ctrl_lli_last = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
},
|
||||
{
|
||||
.number = U300_DMA_APEX_TX,
|
||||
@ -1080,7 +1157,7 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
|
||||
COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_DISABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY |
|
||||
@ -1252,15 +1329,77 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
|
||||
.name = "XGAM PDI",
|
||||
.priority_high = 0,
|
||||
},
|
||||
/*
|
||||
* Don't set up device address, burst count or size of src
|
||||
* or dst bus for this peripheral - handled by PrimeCell
|
||||
* DMA extension.
|
||||
*/
|
||||
{
|
||||
.number = U300_DMA_SPI_TX,
|
||||
.name = "SPI TX",
|
||||
.priority_high = 0,
|
||||
.param.config = COH901318_CX_CFG_CH_DISABLE |
|
||||
COH901318_CX_CFG_LCR_DISABLE |
|
||||
COH901318_CX_CFG_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CFG_BE_IRQ_ENABLE,
|
||||
.param.ctrl_lli_chained = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_DISABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_DISABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
.param.ctrl_lli = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_DISABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
.param.ctrl_lli_last = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_DISABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
},
|
||||
{
|
||||
.number = U300_DMA_SPI_RX,
|
||||
.name = "SPI RX",
|
||||
.priority_high = 0,
|
||||
.param.config = COH901318_CX_CFG_CH_DISABLE |
|
||||
COH901318_CX_CFG_LCR_DISABLE |
|
||||
COH901318_CX_CFG_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CFG_BE_IRQ_ENABLE,
|
||||
.param.ctrl_lli_chained = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_DISABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_DISABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
.param.ctrl_lli = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_DISABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
.param.ctrl_lli_last = 0 |
|
||||
COH901318_CX_CTRL_TC_ENABLE |
|
||||
COH901318_CX_CTRL_MASTER_MODE_M1RW |
|
||||
COH901318_CX_CTRL_TCP_DISABLE |
|
||||
COH901318_CX_CTRL_TC_IRQ_ENABLE |
|
||||
COH901318_CX_CTRL_HSP_ENABLE |
|
||||
COH901318_CX_CTRL_HSS_DISABLE |
|
||||
COH901318_CX_CTRL_DDMA_LEGACY,
|
||||
|
||||
},
|
||||
{
|
||||
.number = U300_DMA_GENERAL_PURPOSE_0,
|
||||
@ -1617,7 +1756,7 @@ static void __init u300_init_check_chip(void)
|
||||
#endif
|
||||
#ifdef CONFIG_MACH_U300_BS335
|
||||
if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) {
|
||||
printk(KERN_ERR "Platform configured for BS365 " \
|
||||
printk(KERN_ERR "Platform configured for BS335 " \
|
||||
" with DB3350 but %s detected, expect problems!",
|
||||
chipname);
|
||||
}
|
||||
@ -1692,12 +1831,12 @@ void __init u300_init_devices(void)
|
||||
/* Register subdevices on the I2C buses */
|
||||
u300_i2c_register_board_devices();
|
||||
|
||||
/* Register subdevices on the SPI bus */
|
||||
u300_spi_register_board_devices();
|
||||
|
||||
/* Register the platform devices */
|
||||
platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
|
||||
|
||||
/* Register subdevices on the SPI bus */
|
||||
u300_spi_register_board_devices();
|
||||
|
||||
#ifndef CONFIG_MACH_U300_SEMI_IS_SHARED
|
||||
/*
|
||||
* Enable SEMI self refresh. Self-refresh of the SDRAM is entered when
|
||||
|
@ -102,6 +102,7 @@ struct coh901318_platform {
|
||||
const int max_channels;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COH901318
|
||||
/**
|
||||
* coh901318_filter_id() - DMA channel filter function
|
||||
* @chan: dma channel handle
|
||||
@ -110,6 +111,12 @@ struct coh901318_platform {
|
||||
* In dma_request_channel() it specifies what channel id to be requested
|
||||
*/
|
||||
bool coh901318_filter_id(struct dma_chan *chan, void *chan_id);
|
||||
#else
|
||||
static inline bool coh901318_filter_id(struct dma_chan *chan, void *chan_id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DMA Controller - this access the static mappings of the coh901318 dma.
|
||||
|
@ -3,159 +3,52 @@
|
||||
* arch/arm/mach-u300/mmc.c
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2009 ST-Ericsson AB
|
||||
* Copyright (C) 2009 ST-Ericsson SA
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*
|
||||
* Author: Linus Walleij <linus.walleij@stericsson.com>
|
||||
* Author: Johan Lundin <johan.lundin@stericsson.com>
|
||||
* Author: Johan Lundin
|
||||
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
|
||||
*/
|
||||
#include <linux/device.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/amba/mmci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <mach/coh901318.h>
|
||||
#include <mach/dma_channels.h>
|
||||
|
||||
#include "mmc.h"
|
||||
#include "padmux.h"
|
||||
|
||||
struct mmci_card_event {
|
||||
struct input_dev *mmc_input;
|
||||
int mmc_inserted;
|
||||
struct work_struct workq;
|
||||
struct mmci_platform_data mmc0_plat_data;
|
||||
};
|
||||
|
||||
static unsigned int mmc_status(struct device *dev)
|
||||
{
|
||||
struct mmci_card_event *mmci_card = container_of(
|
||||
dev->platform_data,
|
||||
struct mmci_card_event, mmc0_plat_data);
|
||||
|
||||
return mmci_card->mmc_inserted;
|
||||
}
|
||||
|
||||
static int mmci_callback(void *data)
|
||||
{
|
||||
struct mmci_card_event *mmci_card = data;
|
||||
|
||||
disable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD);
|
||||
schedule_work(&mmci_card->workq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t gpio_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct mmci_card_event *mmci_card = container_of(
|
||||
dev->platform_data,
|
||||
struct mmci_card_event, mmc0_plat_data);
|
||||
|
||||
|
||||
return sprintf(buf, "%d\n", !mmci_card->mmc_inserted);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(mmc_inserted, S_IRUGO, gpio_show, NULL);
|
||||
|
||||
static void _mmci_callback(struct work_struct *ws)
|
||||
{
|
||||
|
||||
struct mmci_card_event *mmci_card = container_of(
|
||||
ws,
|
||||
struct mmci_card_event, workq);
|
||||
|
||||
mdelay(20);
|
||||
|
||||
mmci_card->mmc_inserted = !gpio_get_value(U300_GPIO_PIN_MMC_CD);
|
||||
|
||||
input_report_switch(mmci_card->mmc_input, KEY_INSERT,
|
||||
mmci_card->mmc_inserted);
|
||||
input_sync(mmci_card->mmc_input);
|
||||
|
||||
pr_debug("MMC/SD card was %s\n",
|
||||
mmci_card->mmc_inserted ? "inserted" : "removed");
|
||||
|
||||
enable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD, mmci_card->mmc_inserted);
|
||||
}
|
||||
|
||||
int __devinit mmc_init(struct amba_device *adev)
|
||||
{
|
||||
struct mmci_card_event *mmci_card;
|
||||
struct device *mmcsd_device = &adev->dev;
|
||||
struct pmx *pmx;
|
||||
int ret = 0;
|
||||
|
||||
mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL);
|
||||
if (!mmci_card)
|
||||
return -ENOMEM;
|
||||
|
||||
static struct mmci_platform_data mmc0_plat_data = {
|
||||
/*
|
||||
* Do not set ocr_mask or voltage translation function,
|
||||
* we have a regulator we can control instead.
|
||||
*/
|
||||
/* Nominally 2.85V on our platform */
|
||||
mmci_card->mmc0_plat_data.f_max = 24000000;
|
||||
mmci_card->mmc0_plat_data.status = mmc_status;
|
||||
mmci_card->mmc0_plat_data.gpio_wp = -1;
|
||||
mmci_card->mmc0_plat_data.gpio_cd = -1;
|
||||
mmci_card->mmc0_plat_data.capabilities = MMC_CAP_MMC_HIGHSPEED |
|
||||
MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
|
||||
.f_max = 24000000,
|
||||
.gpio_wp = -1,
|
||||
.gpio_cd = U300_GPIO_PIN_MMC_CD,
|
||||
.cd_invert = true,
|
||||
.capabilities = MMC_CAP_MMC_HIGHSPEED |
|
||||
MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
|
||||
#ifdef CONFIG_COH901318
|
||||
.dma_filter = coh901318_filter_id,
|
||||
.dma_rx_param = (void *) U300_DMA_MMCSD_RX_TX,
|
||||
/* Don't specify a TX channel, this RX channel is bidirectional */
|
||||
#endif
|
||||
};
|
||||
|
||||
mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data;
|
||||
int __devinit mmc_init(struct amba_device *adev)
|
||||
{
|
||||
struct device *mmcsd_device = &adev->dev;
|
||||
struct pmx *pmx;
|
||||
int ret = 0;
|
||||
|
||||
INIT_WORK(&mmci_card->workq, _mmci_callback);
|
||||
|
||||
ret = gpio_request(U300_GPIO_PIN_MMC_CD, "MMC card detection");
|
||||
if (ret) {
|
||||
printk(KERN_CRIT "Could not allocate MMC card detection " \
|
||||
"GPIO pin\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = gpio_direction_input(U300_GPIO_PIN_MMC_CD);
|
||||
if (ret) {
|
||||
printk(KERN_CRIT "Invalid GPIO pin requested\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = sysfs_create_file(&mmcsd_device->kobj,
|
||||
&dev_attr_mmc_inserted.attr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mmci_card->mmc_input = input_allocate_device();
|
||||
if (!mmci_card->mmc_input) {
|
||||
printk(KERN_CRIT "Could not allocate MMC input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mmci_card->mmc_input->name = "MMC insert notification";
|
||||
mmci_card->mmc_input->id.bustype = BUS_HOST;
|
||||
mmci_card->mmc_input->id.vendor = 0;
|
||||
mmci_card->mmc_input->id.product = 0;
|
||||
mmci_card->mmc_input->id.version = 0x0100;
|
||||
mmci_card->mmc_input->dev.parent = mmcsd_device;
|
||||
input_set_capability(mmci_card->mmc_input, EV_SW, KEY_INSERT);
|
||||
|
||||
/*
|
||||
* Since this must always be compiled into the kernel, this input
|
||||
* is never unregistered or free:ed.
|
||||
*/
|
||||
ret = input_register_device(mmci_card->mmc_input);
|
||||
if (ret) {
|
||||
input_free_device(mmci_card->mmc_input);
|
||||
goto out;
|
||||
}
|
||||
|
||||
input_set_drvdata(mmci_card->mmc_input, mmci_card);
|
||||
mmcsd_device->platform_data = &mmc0_plat_data;
|
||||
|
||||
/*
|
||||
* Setup padmuxing for MMC. Since this must always be
|
||||
@ -171,12 +64,5 @@ int __devinit mmc_init(struct amba_device *adev)
|
||||
pr_warning("Could not activate padmuxing\n");
|
||||
}
|
||||
|
||||
ret = gpio_register_callback(U300_GPIO_PIN_MMC_CD, mmci_callback,
|
||||
mmci_card);
|
||||
|
||||
schedule_work(&mmci_card->workq);
|
||||
|
||||
printk(KERN_INFO "Registered MMC insert/remove notification\n");
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -11,6 +11,9 @@
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/amba/pl022.h>
|
||||
#include <linux/err.h>
|
||||
#include <mach/coh901318.h>
|
||||
#include <mach/dma_channels.h>
|
||||
|
||||
#include "padmux.h"
|
||||
|
||||
/*
|
||||
@ -30,11 +33,8 @@ static void select_dummy_chip(u32 chipselect)
|
||||
}
|
||||
|
||||
struct pl022_config_chip dummy_chip_info = {
|
||||
/*
|
||||
* available POLLING_TRANSFER and INTERRUPT_TRANSFER,
|
||||
* DMA_TRANSFER does not work
|
||||
*/
|
||||
.com_mode = INTERRUPT_TRANSFER,
|
||||
/* available POLLING_TRANSFER, INTERRUPT_TRANSFER, DMA_TRANSFER */
|
||||
.com_mode = DMA_TRANSFER,
|
||||
.iface = SSP_INTERFACE_MOTOROLA_SPI,
|
||||
/* We can only act as master but SSP_SLAVE is possible in theory */
|
||||
.hierarchy = SSP_MASTER,
|
||||
@ -75,8 +75,6 @@ static struct spi_board_info u300_spi_devices[] = {
|
||||
static struct pl022_ssp_controller ssp_platform_data = {
|
||||
/* If you have several SPI buses this varies, we have only bus 0 */
|
||||
.bus_id = 0,
|
||||
/* Set this to 1 when we think we got DMA working */
|
||||
.enable_dma = 0,
|
||||
/*
|
||||
* On the APP CPU GPIO 4, 5 and 6 are connected as generic
|
||||
* chip selects for SPI. (Same on U330, U335 and U365.)
|
||||
@ -84,6 +82,14 @@ static struct pl022_ssp_controller ssp_platform_data = {
|
||||
* and do padmuxing accordingly too.
|
||||
*/
|
||||
.num_chipselect = 3,
|
||||
#ifdef CONFIG_COH901318
|
||||
.enable_dma = 1,
|
||||
.dma_filter = coh901318_filter_id,
|
||||
.dma_rx_param = (void *) U300_DMA_SPI_RX,
|
||||
.dma_tx_param = (void *) U300_DMA_SPI_TX,
|
||||
#else
|
||||
.enable_dma = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -109,6 +115,7 @@ void __init u300_spi_init(struct amba_device *adev)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __init u300_spi_register_board_devices(void)
|
||||
{
|
||||
/* Register any SPI devices */
|
||||
|
@ -3,16 +3,18 @@
|
||||
#
|
||||
|
||||
obj-y := clock.o cpu.o devices.o devices-common.o \
|
||||
id.o
|
||||
id.o usb.o
|
||||
obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o
|
||||
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o
|
||||
obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \
|
||||
board-mop500-keypads.o
|
||||
board-mop500-regulators.o \
|
||||
board-mop500-uib.o board-mop500-stuib.o \
|
||||
board-mop500-u8500uib.o \
|
||||
board-mop500-pins.o
|
||||
obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||
obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o
|
||||
obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o
|
||||
obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o
|
||||
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
|
||||
|
@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
* License Terms: GNU General Public License v2
|
||||
*
|
||||
* Keypad layouts for various boards
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/stmpe.h>
|
||||
#include <linux/mfd/tc3589x.h>
|
||||
#include <linux/input/matrix_keypad.h>
|
||||
|
||||
#include <plat/pincfg.h>
|
||||
#include <plat/ske.h>
|
||||
|
||||
#include <mach/devices.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "devices-db8500.h"
|
||||
#include "board-mop500.h"
|
||||
|
||||
/* STMPE/SKE keypad use this key layout */
|
||||
static const unsigned int mop500_keymap[] = {
|
||||
KEY(2, 5, KEY_END),
|
||||
KEY(4, 1, KEY_POWER),
|
||||
KEY(3, 5, KEY_VOLUMEDOWN),
|
||||
KEY(1, 3, KEY_3),
|
||||
KEY(5, 2, KEY_RIGHT),
|
||||
KEY(5, 0, KEY_9),
|
||||
|
||||
KEY(0, 5, KEY_MENU),
|
||||
KEY(7, 6, KEY_ENTER),
|
||||
KEY(4, 5, KEY_0),
|
||||
KEY(6, 7, KEY_2),
|
||||
KEY(3, 4, KEY_UP),
|
||||
KEY(3, 3, KEY_DOWN),
|
||||
|
||||
KEY(6, 4, KEY_SEND),
|
||||
KEY(6, 2, KEY_BACK),
|
||||
KEY(4, 2, KEY_VOLUMEUP),
|
||||
KEY(5, 5, KEY_1),
|
||||
KEY(4, 3, KEY_LEFT),
|
||||
KEY(3, 2, KEY_7),
|
||||
};
|
||||
|
||||
static const struct matrix_keymap_data mop500_keymap_data = {
|
||||
.keymap = mop500_keymap,
|
||||
.keymap_size = ARRAY_SIZE(mop500_keymap),
|
||||
};
|
||||
|
||||
/*
|
||||
* Nomadik SKE keypad
|
||||
*/
|
||||
#define ROW_PIN_I0 164
|
||||
#define ROW_PIN_I1 163
|
||||
#define ROW_PIN_I2 162
|
||||
#define ROW_PIN_I3 161
|
||||
#define ROW_PIN_I4 156
|
||||
#define ROW_PIN_I5 155
|
||||
#define ROW_PIN_I6 154
|
||||
#define ROW_PIN_I7 153
|
||||
#define COL_PIN_O0 168
|
||||
#define COL_PIN_O1 167
|
||||
#define COL_PIN_O2 166
|
||||
#define COL_PIN_O3 165
|
||||
#define COL_PIN_O4 160
|
||||
#define COL_PIN_O5 159
|
||||
#define COL_PIN_O6 158
|
||||
#define COL_PIN_O7 157
|
||||
|
||||
#define SKE_KPD_MAX_ROWS 8
|
||||
#define SKE_KPD_MAX_COLS 8
|
||||
|
||||
static int ske_kp_rows[] = {
|
||||
ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
|
||||
ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
|
||||
};
|
||||
|
||||
/*
|
||||
* ske_set_gpio_row: request and set gpio rows
|
||||
*/
|
||||
static int ske_set_gpio_row(int gpio)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_request(gpio, "ske-kp");
|
||||
if (ret < 0) {
|
||||
pr_err("ske_set_gpio_row: gpio request failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_direction_output(gpio, 1);
|
||||
if (ret < 0) {
|
||||
pr_err("ske_set_gpio_row: gpio direction failed\n");
|
||||
gpio_free(gpio);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* ske_kp_init - enable the gpio configuration
|
||||
*/
|
||||
static int ske_kp_init(void)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
|
||||
ret = ske_set_gpio_row(ske_kp_rows[i]);
|
||||
if (ret < 0) {
|
||||
pr_err("ske_kp_init: failed init\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ske_keypad_platform_data ske_keypad_board = {
|
||||
.init = ske_kp_init,
|
||||
.keymap_data = &mop500_keymap_data,
|
||||
.no_autorepeat = true,
|
||||
.krow = SKE_KPD_MAX_ROWS, /* 8x8 matrix */
|
||||
.kcol = SKE_KPD_MAX_COLS,
|
||||
.debounce_ms = 40, /* in millisecs */
|
||||
};
|
||||
|
||||
/*
|
||||
* STMPE1601
|
||||
*/
|
||||
static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
|
||||
.debounce_ms = 64,
|
||||
.scan_count = 8,
|
||||
.no_autorepeat = true,
|
||||
.keymap_data = &mop500_keymap_data,
|
||||
};
|
||||
|
||||
static struct stmpe_platform_data stmpe1601_data = {
|
||||
.id = 1,
|
||||
.blocks = STMPE_BLOCK_KEYPAD,
|
||||
.irq_trigger = IRQF_TRIGGER_FALLING,
|
||||
.irq_base = MOP500_STMPE1601_IRQ(0),
|
||||
.keypad = &stmpe1601_keypad_data,
|
||||
.autosleep = true,
|
||||
.autosleep_timeout = 1024,
|
||||
};
|
||||
|
||||
static struct i2c_board_info mop500_i2c0_devices_stuib[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("stmpe1601", 0x40),
|
||||
.irq = NOMADIK_GPIO_TO_IRQ(218),
|
||||
.platform_data = &stmpe1601_data,
|
||||
.flags = I2C_CLIENT_WAKE,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* TC35893
|
||||
*/
|
||||
|
||||
static const unsigned int uib_keymap[] = {
|
||||
KEY(3, 1, KEY_END),
|
||||
KEY(4, 1, KEY_POWER),
|
||||
KEY(6, 4, KEY_VOLUMEDOWN),
|
||||
KEY(4, 2, KEY_EMAIL),
|
||||
KEY(3, 3, KEY_RIGHT),
|
||||
KEY(2, 5, KEY_BACKSPACE),
|
||||
|
||||
KEY(6, 7, KEY_MENU),
|
||||
KEY(5, 0, KEY_ENTER),
|
||||
KEY(4, 3, KEY_0),
|
||||
KEY(3, 4, KEY_DOT),
|
||||
KEY(5, 2, KEY_UP),
|
||||
KEY(3, 5, KEY_DOWN),
|
||||
|
||||
KEY(4, 5, KEY_SEND),
|
||||
KEY(0, 5, KEY_BACK),
|
||||
KEY(6, 2, KEY_VOLUMEUP),
|
||||
KEY(1, 3, KEY_SPACE),
|
||||
KEY(7, 6, KEY_LEFT),
|
||||
KEY(5, 5, KEY_SEARCH),
|
||||
};
|
||||
|
||||
static struct matrix_keymap_data uib_keymap_data = {
|
||||
.keymap = uib_keymap,
|
||||
.keymap_size = ARRAY_SIZE(uib_keymap),
|
||||
};
|
||||
|
||||
static struct tc3589x_keypad_platform_data tc35893_data = {
|
||||
.krow = TC_KPD_ROWS,
|
||||
.kcol = TC_KPD_COLUMNS,
|
||||
.debounce_period = TC_KPD_DEBOUNCE_PERIOD,
|
||||
.settle_time = TC_KPD_SETTLE_TIME,
|
||||
.irqtype = IRQF_TRIGGER_FALLING,
|
||||
.enable_wakeup = true,
|
||||
.keymap_data = &uib_keymap_data,
|
||||
.no_autorepeat = true,
|
||||
};
|
||||
|
||||
static struct tc3589x_platform_data tc3589x_keypad_data = {
|
||||
.block = TC3589x_BLOCK_KEYPAD,
|
||||
.keypad = &tc35893_data,
|
||||
.irq_base = MOP500_EGPIO_IRQ_BASE,
|
||||
};
|
||||
|
||||
static struct i2c_board_info mop500_i2c0_devices_uib[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("tc3589x", 0x44),
|
||||
.platform_data = &tc3589x_keypad_data,
|
||||
.irq = NOMADIK_GPIO_TO_IRQ(218),
|
||||
.flags = I2C_CLIENT_WAKE,
|
||||
},
|
||||
};
|
||||
|
||||
void mop500_keypad_init(void)
|
||||
{
|
||||
db8500_add_ske_keypad(&ske_keypad_board);
|
||||
|
||||
i2c_register_board_info(0, mop500_i2c0_devices_stuib,
|
||||
ARRAY_SIZE(mop500_i2c0_devices_stuib));
|
||||
|
||||
i2c_register_board_info(0, mop500_i2c0_devices_uib,
|
||||
ARRAY_SIZE(mop500_i2c0_devices_uib));
|
||||
|
||||
}
|
241
arch/arm/mach-ux500/board-mop500-pins.c
Normal file
241
arch/arm/mach-ux500/board-mop500-pins.c
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <plat/pincfg.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "pins-db8500.h"
|
||||
|
||||
static pin_cfg_t mop500_pins_common[] = {
|
||||
/* I2C */
|
||||
GPIO147_I2C0_SCL,
|
||||
GPIO148_I2C0_SDA,
|
||||
GPIO16_I2C1_SCL,
|
||||
GPIO17_I2C1_SDA,
|
||||
GPIO10_I2C2_SDA,
|
||||
GPIO11_I2C2_SCL,
|
||||
GPIO229_I2C3_SDA,
|
||||
GPIO230_I2C3_SCL,
|
||||
|
||||
/* MSP0 */
|
||||
GPIO12_MSP0_TXD,
|
||||
GPIO13_MSP0_TFS,
|
||||
GPIO14_MSP0_TCK,
|
||||
GPIO15_MSP0_RXD,
|
||||
|
||||
/* MSP2: HDMI */
|
||||
GPIO193_MSP2_TXD,
|
||||
GPIO194_MSP2_TCK,
|
||||
GPIO195_MSP2_TFS,
|
||||
GPIO196_MSP2_RXD | PIN_OUTPUT_LOW,
|
||||
|
||||
/* Touch screen INTERFACE */
|
||||
GPIO84_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT1 */
|
||||
|
||||
/* STMPE1601/tc35893 keypad IRQ */
|
||||
GPIO218_GPIO | PIN_INPUT_PULLUP,
|
||||
|
||||
/* MMC0 (MicroSD card) */
|
||||
GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH,
|
||||
GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH,
|
||||
GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH,
|
||||
|
||||
GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL,
|
||||
GPIO23_MC0_CLK | PIN_OUTPUT_LOW,
|
||||
GPIO24_MC0_CMD | PIN_INPUT_PULLUP,
|
||||
GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP,
|
||||
GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP,
|
||||
GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP,
|
||||
GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP,
|
||||
|
||||
/* SDI1 (SDIO) */
|
||||
GPIO208_MC1_CLK | PIN_OUTPUT_LOW,
|
||||
GPIO209_MC1_FBCLK | PIN_INPUT_NOPULL,
|
||||
GPIO210_MC1_CMD | PIN_INPUT_PULLUP,
|
||||
GPIO211_MC1_DAT0 | PIN_INPUT_PULLUP,
|
||||
GPIO212_MC1_DAT1 | PIN_INPUT_PULLUP,
|
||||
GPIO213_MC1_DAT2 | PIN_INPUT_PULLUP,
|
||||
GPIO214_MC1_DAT3 | PIN_INPUT_PULLUP,
|
||||
|
||||
/* MMC2 (On-board DATA INTERFACE eMMC) */
|
||||
GPIO128_MC2_CLK | PIN_OUTPUT_LOW,
|
||||
GPIO129_MC2_CMD | PIN_INPUT_PULLUP,
|
||||
GPIO130_MC2_FBCLK | PIN_INPUT_NOPULL,
|
||||
GPIO131_MC2_DAT0 | PIN_INPUT_PULLUP,
|
||||
GPIO132_MC2_DAT1 | PIN_INPUT_PULLUP,
|
||||
GPIO133_MC2_DAT2 | PIN_INPUT_PULLUP,
|
||||
GPIO134_MC2_DAT3 | PIN_INPUT_PULLUP,
|
||||
GPIO135_MC2_DAT4 | PIN_INPUT_PULLUP,
|
||||
GPIO136_MC2_DAT5 | PIN_INPUT_PULLUP,
|
||||
GPIO137_MC2_DAT6 | PIN_INPUT_PULLUP,
|
||||
GPIO138_MC2_DAT7 | PIN_INPUT_PULLUP,
|
||||
|
||||
/* MMC4 (On-board STORAGE INTERFACE eMMC) */
|
||||
GPIO197_MC4_DAT3 | PIN_INPUT_PULLUP,
|
||||
GPIO198_MC4_DAT2 | PIN_INPUT_PULLUP,
|
||||
GPIO199_MC4_DAT1 | PIN_INPUT_PULLUP,
|
||||
GPIO200_MC4_DAT0 | PIN_INPUT_PULLUP,
|
||||
GPIO201_MC4_CMD | PIN_INPUT_PULLUP,
|
||||
GPIO202_MC4_FBCLK | PIN_INPUT_NOPULL,
|
||||
GPIO203_MC4_CLK | PIN_OUTPUT_LOW,
|
||||
GPIO204_MC4_DAT7 | PIN_INPUT_PULLUP,
|
||||
GPIO205_MC4_DAT6 | PIN_INPUT_PULLUP,
|
||||
GPIO206_MC4_DAT5 | PIN_INPUT_PULLUP,
|
||||
GPIO207_MC4_DAT4 | PIN_INPUT_PULLUP,
|
||||
|
||||
/* SKE keypad */
|
||||
GPIO153_KP_I7,
|
||||
GPIO154_KP_I6,
|
||||
GPIO155_KP_I5,
|
||||
GPIO156_KP_I4,
|
||||
GPIO157_KP_O7,
|
||||
GPIO158_KP_O6,
|
||||
GPIO159_KP_O5,
|
||||
GPIO160_KP_O4,
|
||||
GPIO161_KP_I3,
|
||||
GPIO162_KP_I2,
|
||||
GPIO163_KP_I1,
|
||||
GPIO164_KP_I0,
|
||||
GPIO165_KP_O3,
|
||||
GPIO166_KP_O2,
|
||||
GPIO167_KP_O1,
|
||||
GPIO168_KP_O0,
|
||||
|
||||
/* UART */
|
||||
GPIO0_U0_CTSn | PIN_INPUT_PULLUP,
|
||||
GPIO1_U0_RTSn | PIN_OUTPUT_HIGH,
|
||||
GPIO2_U0_RXD | PIN_INPUT_PULLUP,
|
||||
GPIO3_U0_TXD | PIN_OUTPUT_HIGH,
|
||||
|
||||
GPIO29_U2_RXD | PIN_INPUT_PULLUP,
|
||||
GPIO30_U2_TXD | PIN_OUTPUT_HIGH,
|
||||
GPIO31_U2_CTSn | PIN_INPUT_PULLUP,
|
||||
GPIO32_U2_RTSn | PIN_OUTPUT_HIGH,
|
||||
|
||||
/* Display & HDMI HW sync */
|
||||
GPIO68_LCD_VSI0 | PIN_INPUT_PULLUP,
|
||||
GPIO69_LCD_VSI1 | PIN_INPUT_PULLUP,
|
||||
};
|
||||
|
||||
static pin_cfg_t mop500_pins_default[] = {
|
||||
/* SSP0 */
|
||||
GPIO143_SSP0_CLK,
|
||||
GPIO144_SSP0_FRM,
|
||||
GPIO145_SSP0_RXD | PIN_PULL_DOWN,
|
||||
GPIO146_SSP0_TXD,
|
||||
|
||||
|
||||
GPIO217_GPIO | PIN_INPUT_PULLUP, /* TC35892 IRQ */
|
||||
|
||||
/* SDI0 (MicroSD card) */
|
||||
GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH,
|
||||
|
||||
/* UART */
|
||||
GPIO4_U1_RXD | PIN_INPUT_PULLUP,
|
||||
GPIO5_U1_TXD | PIN_OUTPUT_HIGH,
|
||||
GPIO6_U1_CTSn | PIN_INPUT_PULLUP,
|
||||
GPIO7_U1_RTSn | PIN_OUTPUT_HIGH,
|
||||
};
|
||||
|
||||
static pin_cfg_t mop500_pins_hrefv60[] = {
|
||||
/* WLAN */
|
||||
GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */
|
||||
GPIO85_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */
|
||||
|
||||
/* XENON Flashgun INTERFACE */
|
||||
GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */
|
||||
GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */
|
||||
GPIO170_GPIO | PIN_OUTPUT_LOW, /* XENON_CHARGE */
|
||||
|
||||
/* Assistant LED INTERFACE */
|
||||
GPIO21_GPIO | PIN_OUTPUT_LOW, /* XENON_EN1 */
|
||||
GPIO64_IP_GPIO4 | PIN_OUTPUT_LOW, /* XENON_EN2 */
|
||||
|
||||
/* Magnetometer */
|
||||
GPIO31_GPIO | PIN_INPUT_PULLUP, /* magnetometer_INT */
|
||||
GPIO32_GPIO | PIN_INPUT_PULLDOWN, /* Magnetometer DRDY */
|
||||
|
||||
/* Display Interface */
|
||||
GPIO65_GPIO | PIN_OUTPUT_LOW, /* DISP1 RST */
|
||||
GPIO66_GPIO | PIN_OUTPUT_LOW, /* DISP2 RST */
|
||||
|
||||
/* Touch screen INTERFACE */
|
||||
GPIO143_GPIO | PIN_OUTPUT_LOW,/*TOUCH_RST1 */
|
||||
|
||||
/* Touch screen INTERFACE 2 */
|
||||
GPIO67_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT2 */
|
||||
GPIO146_GPIO | PIN_OUTPUT_LOW,/*TOUCH_RST2 */
|
||||
|
||||
/* ETM_PTM_TRACE INTERFACE */
|
||||
GPIO70_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA23 */
|
||||
GPIO71_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA22 */
|
||||
GPIO72_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA21 */
|
||||
GPIO73_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA20 */
|
||||
GPIO74_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA19 */
|
||||
|
||||
/* NAHJ INTERFACE */
|
||||
GPIO76_GPIO | PIN_OUTPUT_LOW,/* NAHJ_CTRL */
|
||||
GPIO216_GPIO | PIN_OUTPUT_HIGH,/* NAHJ_CTRL_INV */
|
||||
|
||||
/* NFC INTERFACE */
|
||||
GPIO77_GPIO | PIN_OUTPUT_LOW, /* NFC_ENA */
|
||||
GPIO144_GPIO | PIN_INPUT_PULLDOWN, /* NFC_IRQ */
|
||||
GPIO142_GPIO | PIN_OUTPUT_LOW, /* NFC_RESET */
|
||||
|
||||
/* Keyboard MATRIX INTERFACE */
|
||||
GPIO90_MC5_CMD | PIN_OUTPUT_LOW, /* KP_O_1 */
|
||||
GPIO87_MC5_DAT1 | PIN_OUTPUT_LOW, /* KP_O_2 */
|
||||
GPIO86_MC5_DAT0 | PIN_OUTPUT_LOW, /* KP_O_3 */
|
||||
GPIO96_KP_O6 | PIN_OUTPUT_LOW, /* KP_O_6 */
|
||||
GPIO94_KP_O7 | PIN_OUTPUT_LOW, /* KP_O_7 */
|
||||
GPIO93_MC5_DAT4 | PIN_INPUT_PULLUP, /* KP_I_0 */
|
||||
GPIO89_MC5_DAT3 | PIN_INPUT_PULLUP, /* KP_I_2 */
|
||||
GPIO88_MC5_DAT2 | PIN_INPUT_PULLUP, /* KP_I_3 */
|
||||
GPIO91_GPIO | PIN_INPUT_PULLUP, /* FORCE_SENSING_INT */
|
||||
GPIO92_GPIO | PIN_OUTPUT_LOW, /* FORCE_SENSING_RST */
|
||||
GPIO97_GPIO | PIN_OUTPUT_LOW, /* FORCE_SENSING_WU */
|
||||
|
||||
/* DiPro Sensor Interface */
|
||||
GPIO139_GPIO | PIN_INPUT_PULLUP, /* DIPRO_INT */
|
||||
|
||||
/* HAL SWITCH INTERFACE */
|
||||
GPIO145_GPIO | PIN_INPUT_PULLDOWN,/* HAL_SW */
|
||||
|
||||
/* Audio Amplifier Interface */
|
||||
GPIO149_GPIO | PIN_OUTPUT_LOW, /* VAUDIO_HF_EN */
|
||||
|
||||
/* GBF INTERFACE */
|
||||
GPIO171_GPIO | PIN_OUTPUT_LOW, /* GBF_ENA_RESET */
|
||||
|
||||
/* MSP : HDTV INTERFACE */
|
||||
GPIO192_GPIO | PIN_INPUT_PULLDOWN,
|
||||
|
||||
/* ACCELEROMETER_INTERFACE */
|
||||
GPIO82_GPIO | PIN_INPUT_PULLUP, /* ACC_INT1 */
|
||||
GPIO83_GPIO | PIN_INPUT_PULLUP, /* ACC_INT2 */
|
||||
|
||||
/* Proximity Sensor */
|
||||
GPIO217_GPIO | PIN_INPUT_PULLUP,
|
||||
|
||||
|
||||
};
|
||||
|
||||
void __init mop500_pins_init(void)
|
||||
{
|
||||
nmk_config_pins(mop500_pins_common,
|
||||
ARRAY_SIZE(mop500_pins_common));
|
||||
if (machine_is_hrefv60())
|
||||
nmk_config_pins(mop500_pins_hrefv60,
|
||||
ARRAY_SIZE(mop500_pins_hrefv60));
|
||||
else
|
||||
nmk_config_pins(mop500_pins_default,
|
||||
ARRAY_SIZE(mop500_pins_default));
|
||||
}
|
@ -11,6 +11,56 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/ab8500.h>
|
||||
#include "board-mop500-regulators.h"
|
||||
|
||||
static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
|
||||
/* External displays, connector on board 2v5 power supply */
|
||||
REGULATOR_SUPPLY("vaux12v5", "mcde.0"),
|
||||
/* SFH7741 proximity sensor */
|
||||
REGULATOR_SUPPLY("vcc", "gpio-keys.0"),
|
||||
/* BH1780GLS ambient light sensor */
|
||||
REGULATOR_SUPPLY("vcc", "2-0029"),
|
||||
/* lsm303dlh accelerometer */
|
||||
REGULATOR_SUPPLY("vdd", "3-0018"),
|
||||
/* lsm303dlh magnetometer */
|
||||
REGULATOR_SUPPLY("vdd", "3-001e"),
|
||||
/* Rohm BU21013 Touchscreen devices */
|
||||
REGULATOR_SUPPLY("avdd", "3-005c"),
|
||||
REGULATOR_SUPPLY("avdd", "3-005d"),
|
||||
/* Synaptics RMI4 Touchscreen device */
|
||||
REGULATOR_SUPPLY("vdd", "3-004b"),
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
|
||||
/* On-board eMMC power */
|
||||
REGULATOR_SUPPLY("vmmc", "sdi4"),
|
||||
/* AB8500 audio codec */
|
||||
REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"),
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
|
||||
/* External MMC slot power */
|
||||
REGULATOR_SUPPLY("vmmc", "sdi0"),
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
|
||||
/* TV-out DENC supply */
|
||||
REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"),
|
||||
/* Internal general-purpose ADC */
|
||||
REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"),
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
|
||||
/* SoC core supply, no device */
|
||||
REGULATOR_SUPPLY("v-intcore", NULL),
|
||||
/* USB Transciever */
|
||||
REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"),
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply ab8500_vana_consumers[] = {
|
||||
/* External displays, connector on board, 1v8 power supply */
|
||||
REGULATOR_SUPPLY("vsmps2", "mcde.0"),
|
||||
};
|
||||
|
||||
/* AB8500 regulators */
|
||||
struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
|
||||
@ -23,6 +73,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
|
||||
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
|
||||
REGULATOR_CHANGE_STATUS,
|
||||
},
|
||||
.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
|
||||
.consumer_supplies = ab8500_vaux1_consumers,
|
||||
},
|
||||
/* supplies to the on-board eMMC */
|
||||
[AB8500_LDO_AUX2] = {
|
||||
@ -33,6 +85,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
|
||||
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
|
||||
REGULATOR_CHANGE_STATUS,
|
||||
},
|
||||
.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
|
||||
.consumer_supplies = ab8500_vaux2_consumers,
|
||||
},
|
||||
/* supply for VAUX3, supplies to SDcard slots */
|
||||
[AB8500_LDO_AUX3] = {
|
||||
@ -43,6 +97,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
|
||||
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
|
||||
REGULATOR_CHANGE_STATUS,
|
||||
},
|
||||
.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
|
||||
.consumer_supplies = ab8500_vaux3_consumers,
|
||||
},
|
||||
/* supply for tvout, gpadc, TVOUT LDO */
|
||||
[AB8500_LDO_TVOUT] = {
|
||||
@ -50,6 +106,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
|
||||
.name = "V-TVOUT",
|
||||
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
|
||||
},
|
||||
.num_consumer_supplies = ARRAY_SIZE(ab8500_vtvout_consumers),
|
||||
.consumer_supplies = ab8500_vtvout_consumers,
|
||||
},
|
||||
/* supply for ab8500-vaudio, VAUDIO LDO */
|
||||
[AB8500_LDO_AUDIO] = {
|
||||
@ -85,6 +143,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
|
||||
.name = "V-INTCORE",
|
||||
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
|
||||
},
|
||||
.num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
|
||||
.consumer_supplies = ab8500_vintcore_consumers,
|
||||
},
|
||||
/* supply for U8500 CSI/DSI, VANA LDO */
|
||||
[AB8500_LDO_ANA] = {
|
||||
@ -92,5 +152,7 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
|
||||
.name = "V-CSI/DSI",
|
||||
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
|
||||
},
|
||||
.num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
|
||||
.consumer_supplies = ab8500_vana_consumers,
|
||||
},
|
||||
};
|
||||
|
@ -12,56 +12,14 @@
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <plat/pincfg.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <plat/ste_dma40.h>
|
||||
#include <mach/devices.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "devices-db8500.h"
|
||||
#include "pins-db8500.h"
|
||||
#include "board-mop500.h"
|
||||
|
||||
static pin_cfg_t mop500_sdi_pins[] = {
|
||||
/* SDI0 (MicroSD slot) */
|
||||
GPIO18_MC0_CMDDIR,
|
||||
GPIO19_MC0_DAT0DIR,
|
||||
GPIO20_MC0_DAT2DIR,
|
||||
GPIO21_MC0_DAT31DIR,
|
||||
GPIO22_MC0_FBCLK,
|
||||
GPIO23_MC0_CLK,
|
||||
GPIO24_MC0_CMD,
|
||||
GPIO25_MC0_DAT0,
|
||||
GPIO26_MC0_DAT1,
|
||||
GPIO27_MC0_DAT2,
|
||||
GPIO28_MC0_DAT3,
|
||||
|
||||
/* SDI4 (on-board eMMC) */
|
||||
GPIO197_MC4_DAT3,
|
||||
GPIO198_MC4_DAT2,
|
||||
GPIO199_MC4_DAT1,
|
||||
GPIO200_MC4_DAT0,
|
||||
GPIO201_MC4_CMD,
|
||||
GPIO202_MC4_FBCLK,
|
||||
GPIO203_MC4_CLK,
|
||||
GPIO204_MC4_DAT7,
|
||||
GPIO205_MC4_DAT6,
|
||||
GPIO206_MC4_DAT5,
|
||||
GPIO207_MC4_DAT4,
|
||||
};
|
||||
|
||||
static pin_cfg_t mop500_sdi2_pins[] = {
|
||||
/* SDI2 (POP eMMC) */
|
||||
GPIO128_MC2_CLK,
|
||||
GPIO129_MC2_CMD,
|
||||
GPIO130_MC2_FBCLK,
|
||||
GPIO131_MC2_DAT0,
|
||||
GPIO132_MC2_DAT1,
|
||||
GPIO133_MC2_DAT2,
|
||||
GPIO134_MC2_DAT3,
|
||||
GPIO135_MC2_DAT4,
|
||||
GPIO136_MC2_DAT5,
|
||||
GPIO137_MC2_DAT6,
|
||||
GPIO138_MC2_DAT7,
|
||||
};
|
||||
#include "ste-dma40-db8500.h"
|
||||
|
||||
/*
|
||||
* SDI 0 (MicroSD slot)
|
||||
@ -86,48 +44,134 @@ static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
|
||||
MCI_DATA2DIREN | MCI_DATA31DIREN;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct mmci_platform_data mop500_sdi0_data = {
|
||||
.vdd_handler = mop500_sdi0_vdd_handler,
|
||||
.ocr_mask = MMC_VDD_29_30,
|
||||
.f_max = 100000000,
|
||||
.capabilities = MMC_CAP_4_BIT_DATA,
|
||||
.gpio_cd = GPIO_SDMMC_CD,
|
||||
.gpio_wp = -1,
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &mop500_sdi0_dma_cfg_rx,
|
||||
.dma_tx_param = &mop500_sdi0_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
||||
|
||||
void mop500_sdi_tc35892_init(void)
|
||||
/* GPIO pins used by the sdi0 level shifter */
|
||||
static int sdi0_en = -1;
|
||||
static int sdi0_vsel = -1;
|
||||
|
||||
static void sdi0_configure(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_request(GPIO_SDMMC_EN, "SDMMC_EN");
|
||||
ret = gpio_request(sdi0_en, "level shifter enable");
|
||||
if (!ret)
|
||||
ret = gpio_request(GPIO_SDMMC_1V8_3V_SEL,
|
||||
"GPIO_SDMMC_1V8_3V_SEL");
|
||||
if (ret)
|
||||
ret = gpio_request(sdi0_vsel,
|
||||
"level shifter 1v8-3v select");
|
||||
|
||||
if (ret) {
|
||||
pr_warning("unable to config sdi0 gpios for level shifter.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1);
|
||||
gpio_direction_output(GPIO_SDMMC_EN, 0);
|
||||
/* Select the default 2.9V and enable level shifter */
|
||||
gpio_direction_output(sdi0_vsel, 0);
|
||||
gpio_direction_output(sdi0_en, 1);
|
||||
|
||||
/* Add the device */
|
||||
db8500_add_sdi0(&mop500_sdi0_data);
|
||||
}
|
||||
|
||||
void mop500_sdi_tc35892_init(void)
|
||||
{
|
||||
mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD;
|
||||
sdi0_en = GPIO_SDMMC_EN;
|
||||
sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL;
|
||||
sdi0_configure();
|
||||
}
|
||||
|
||||
/*
|
||||
* SDI 2 (POP eMMC, not on DB8500ed)
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV28_SD_MM2_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV28_SD_MM2_TX,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct mmci_platform_data mop500_sdi2_data = {
|
||||
.ocr_mask = MMC_VDD_165_195,
|
||||
.f_max = 100000000,
|
||||
.capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
|
||||
.gpio_cd = -1,
|
||||
.gpio_wp = -1,
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &mop500_sdi2_dma_cfg_rx,
|
||||
.dma_tx_param = &mop500_sdi2_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* SDI 4 (on-board eMMC)
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV42_SD_MM4_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV42_SD_MM4_TX,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct mmci_platform_data mop500_sdi4_data = {
|
||||
.ocr_mask = MMC_VDD_29_30,
|
||||
.f_max = 100000000,
|
||||
@ -135,26 +179,32 @@ static struct mmci_platform_data mop500_sdi4_data = {
|
||||
MMC_CAP_MMC_HIGHSPEED,
|
||||
.gpio_cd = -1,
|
||||
.gpio_wp = -1,
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &mop500_sdi4_dma_cfg_rx,
|
||||
.dma_tx_param = &mop500_sdi4_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
||||
|
||||
void __init mop500_sdi_init(void)
|
||||
{
|
||||
nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins));
|
||||
|
||||
/*
|
||||
* sdi0 will finally be added when the TC35892 initializes and calls
|
||||
* mop500_sdi_tc35892_init() above.
|
||||
*/
|
||||
|
||||
/* PoP:ed eMMC */
|
||||
if (!cpu_is_u8500ed()) {
|
||||
nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins));
|
||||
/* POP eMMC on v1.0 has problems with high speed */
|
||||
/* PoP:ed eMMC on top of DB8500 v1.0 has problems with high speed */
|
||||
if (!cpu_is_u8500v10())
|
||||
mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
|
||||
db8500_add_sdi2(&mop500_sdi2_data);
|
||||
}
|
||||
|
||||
/* On-board eMMC */
|
||||
db8500_add_sdi4(&mop500_sdi4_data);
|
||||
|
||||
if (machine_is_hrefv60()) {
|
||||
mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
|
||||
sdi0_en = HREFV60_SDMMC_EN_GPIO;
|
||||
sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
|
||||
sdi0_configure();
|
||||
}
|
||||
/*
|
||||
* On boards with the TC35892 GPIO expander, sdi0 will finally
|
||||
* be added when the TC35892 initializes and calls
|
||||
* mop500_sdi_tc35892_init() above.
|
||||
*/
|
||||
}
|
||||
|
205
arch/arm/mach-ux500/board-mop500-stuib.c
Normal file
205
arch/arm/mach-ux500/board-mop500-stuib.c
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
* License terms: GNU General Public License (GPL), version 2
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mfd/stmpe.h>
|
||||
#include <linux/input/bu21013.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input/matrix_keypad.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include "board-mop500.h"
|
||||
|
||||
/* STMPE/SKE keypad use this key layout */
|
||||
static const unsigned int mop500_keymap[] = {
|
||||
KEY(2, 5, KEY_END),
|
||||
KEY(4, 1, KEY_POWER),
|
||||
KEY(3, 5, KEY_VOLUMEDOWN),
|
||||
KEY(1, 3, KEY_3),
|
||||
KEY(5, 2, KEY_RIGHT),
|
||||
KEY(5, 0, KEY_9),
|
||||
|
||||
KEY(0, 5, KEY_MENU),
|
||||
KEY(7, 6, KEY_ENTER),
|
||||
KEY(4, 5, KEY_0),
|
||||
KEY(6, 7, KEY_2),
|
||||
KEY(3, 4, KEY_UP),
|
||||
KEY(3, 3, KEY_DOWN),
|
||||
|
||||
KEY(6, 4, KEY_SEND),
|
||||
KEY(6, 2, KEY_BACK),
|
||||
KEY(4, 2, KEY_VOLUMEUP),
|
||||
KEY(5, 5, KEY_1),
|
||||
KEY(4, 3, KEY_LEFT),
|
||||
KEY(3, 2, KEY_7),
|
||||
};
|
||||
|
||||
static const struct matrix_keymap_data mop500_keymap_data = {
|
||||
.keymap = mop500_keymap,
|
||||
.keymap_size = ARRAY_SIZE(mop500_keymap),
|
||||
};
|
||||
/*
|
||||
* STMPE1601
|
||||
*/
|
||||
static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
|
||||
.debounce_ms = 64,
|
||||
.scan_count = 8,
|
||||
.no_autorepeat = true,
|
||||
.keymap_data = &mop500_keymap_data,
|
||||
};
|
||||
|
||||
static struct stmpe_platform_data stmpe1601_data = {
|
||||
.id = 1,
|
||||
.blocks = STMPE_BLOCK_KEYPAD,
|
||||
.irq_trigger = IRQF_TRIGGER_FALLING,
|
||||
.irq_base = MOP500_STMPE1601_IRQ(0),
|
||||
.keypad = &stmpe1601_keypad_data,
|
||||
.autosleep = true,
|
||||
.autosleep_timeout = 1024,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("stmpe1601", 0x40),
|
||||
.irq = NOMADIK_GPIO_TO_IRQ(218),
|
||||
.platform_data = &stmpe1601_data,
|
||||
.flags = I2C_CLIENT_WAKE,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* BU21013 ROHM touchscreen interface on the STUIBs
|
||||
*/
|
||||
|
||||
/* tracks number of bu21013 devices being enabled */
|
||||
static int bu21013_devices;
|
||||
|
||||
#define TOUCH_GPIO_PIN 84
|
||||
|
||||
#define TOUCH_XMAX 384
|
||||
#define TOUCH_YMAX 704
|
||||
|
||||
#define PRCMU_CLOCK_OCR 0x1CC
|
||||
#define TSC_EXT_CLOCK_9_6MHZ 0x840000
|
||||
|
||||
/**
|
||||
* bu21013_gpio_board_init : configures the touch panel.
|
||||
* @reset_pin: reset pin number
|
||||
* This function can be used to configures
|
||||
* the voltage and reset the touch panel controller.
|
||||
*/
|
||||
static int bu21013_gpio_board_init(int reset_pin)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
bu21013_devices++;
|
||||
if (bu21013_devices == 1) {
|
||||
retval = gpio_request(reset_pin, "touchp_reset");
|
||||
if (retval) {
|
||||
printk(KERN_ERR "Unable to request gpio reset_pin");
|
||||
return retval;
|
||||
}
|
||||
retval = gpio_direction_output(reset_pin, 1);
|
||||
if (retval < 0) {
|
||||
printk(KERN_ERR "%s: gpio direction failed\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* bu21013_gpio_board_exit : deconfigures the touch panel controller
|
||||
* @reset_pin: reset pin number
|
||||
* This function can be used to deconfigures the chip selection
|
||||
* for touch panel controller.
|
||||
*/
|
||||
static int bu21013_gpio_board_exit(int reset_pin)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (bu21013_devices == 1) {
|
||||
retval = gpio_direction_output(reset_pin, 0);
|
||||
if (retval < 0) {
|
||||
printk(KERN_ERR "%s: gpio direction failed\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
gpio_set_value(reset_pin, 0);
|
||||
}
|
||||
bu21013_devices--;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* bu21013_read_pin_val : get the interrupt pin value
|
||||
* This function can be used to get the interrupt pin value for touch panel
|
||||
* controller.
|
||||
*/
|
||||
static int bu21013_read_pin_val(void)
|
||||
{
|
||||
return gpio_get_value(TOUCH_GPIO_PIN);
|
||||
}
|
||||
|
||||
static struct bu21013_platform_device tsc_plat_device = {
|
||||
.cs_en = bu21013_gpio_board_init,
|
||||
.cs_dis = bu21013_gpio_board_exit,
|
||||
.irq_read_val = bu21013_read_pin_val,
|
||||
.irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
|
||||
.touch_x_max = TOUCH_XMAX,
|
||||
.touch_y_max = TOUCH_YMAX,
|
||||
.ext_clk = false,
|
||||
.x_flip = false,
|
||||
.y_flip = true,
|
||||
};
|
||||
|
||||
static struct bu21013_platform_device tsc_plat2_device = {
|
||||
.cs_en = bu21013_gpio_board_init,
|
||||
.cs_dis = bu21013_gpio_board_exit,
|
||||
.irq_read_val = bu21013_read_pin_val,
|
||||
.irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
|
||||
.touch_x_max = TOUCH_XMAX,
|
||||
.touch_y_max = TOUCH_YMAX,
|
||||
.ext_clk = false,
|
||||
.x_flip = false,
|
||||
.y_flip = true,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("bu21013_tp", 0x5C),
|
||||
.platform_data = &tsc_plat_device,
|
||||
},
|
||||
{
|
||||
I2C_BOARD_INFO("bu21013_tp", 0x5D),
|
||||
.platform_data = &tsc_plat2_device,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
void __init mop500_stuib_init(void)
|
||||
{
|
||||
if (machine_is_hrefv60()) {
|
||||
tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
|
||||
tsc_plat2_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
|
||||
} else {
|
||||
tsc_plat_device.cs_pin = GPIO_BU21013_CS;
|
||||
tsc_plat2_device.cs_pin = GPIO_BU21013_CS;
|
||||
|
||||
}
|
||||
|
||||
mop500_uib_i2c_add(0, mop500_i2c0_devices_stuib,
|
||||
ARRAY_SIZE(mop500_i2c0_devices_stuib));
|
||||
|
||||
mop500_uib_i2c_add(3, u8500_i2c3_devices_stuib,
|
||||
ARRAY_SIZE(u8500_i2c3_devices_stuib));
|
||||
}
|
111
arch/arm/mach-ux500/board-mop500-u8500uib.c
Normal file
111
arch/arm/mach-ux500/board-mop500-u8500uib.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
* Board data for the U8500 UIB, also known as the New UIB
|
||||
* License terms: GNU General Public License (GPL), version 2
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/tc3589x.h>
|
||||
#include <linux/input/matrix_keypad.h>
|
||||
#include <../drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h>
|
||||
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "board-mop500.h"
|
||||
|
||||
/*
|
||||
* Synaptics RMI4 touchscreen interface on the U8500 UIB
|
||||
*/
|
||||
|
||||
/*
|
||||
* Descriptor structure.
|
||||
* Describes the number of i2c devices on the bus that speak RMI.
|
||||
*/
|
||||
static struct synaptics_rmi4_platform_data rmi4_i2c_dev_platformdata = {
|
||||
.irq_number = NOMADIK_GPIO_TO_IRQ(84),
|
||||
.irq_type = (IRQF_TRIGGER_FALLING | IRQF_SHARED),
|
||||
.x_flip = false,
|
||||
.y_flip = true,
|
||||
.regulator_en = false,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata mop500_i2c3_devices_u8500[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("synaptics_rmi4_i2c", 0x4B),
|
||||
.platform_data = &rmi4_i2c_dev_platformdata,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* TC35893
|
||||
*/
|
||||
static const unsigned int u8500_keymap[] = {
|
||||
KEY(3, 1, KEY_END),
|
||||
KEY(4, 1, KEY_POWER),
|
||||
KEY(6, 4, KEY_VOLUMEDOWN),
|
||||
KEY(4, 2, KEY_EMAIL),
|
||||
KEY(3, 3, KEY_RIGHT),
|
||||
KEY(2, 5, KEY_BACKSPACE),
|
||||
|
||||
KEY(6, 7, KEY_MENU),
|
||||
KEY(5, 0, KEY_ENTER),
|
||||
KEY(4, 3, KEY_0),
|
||||
KEY(3, 4, KEY_DOT),
|
||||
KEY(5, 2, KEY_UP),
|
||||
KEY(3, 5, KEY_DOWN),
|
||||
|
||||
KEY(4, 5, KEY_SEND),
|
||||
KEY(0, 5, KEY_BACK),
|
||||
KEY(6, 2, KEY_VOLUMEUP),
|
||||
KEY(1, 3, KEY_SPACE),
|
||||
KEY(7, 6, KEY_LEFT),
|
||||
KEY(5, 5, KEY_SEARCH),
|
||||
};
|
||||
|
||||
static struct matrix_keymap_data u8500_keymap_data = {
|
||||
.keymap = u8500_keymap,
|
||||
.keymap_size = ARRAY_SIZE(u8500_keymap),
|
||||
};
|
||||
|
||||
static struct tc3589x_keypad_platform_data tc35893_data = {
|
||||
.krow = TC_KPD_ROWS,
|
||||
.kcol = TC_KPD_COLUMNS,
|
||||
.debounce_period = TC_KPD_DEBOUNCE_PERIOD,
|
||||
.settle_time = TC_KPD_SETTLE_TIME,
|
||||
.irqtype = IRQF_TRIGGER_FALLING,
|
||||
.enable_wakeup = true,
|
||||
.keymap_data = &u8500_keymap_data,
|
||||
.no_autorepeat = true,
|
||||
};
|
||||
|
||||
static struct tc3589x_platform_data tc3589x_keypad_data = {
|
||||
.block = TC3589x_BLOCK_KEYPAD,
|
||||
.keypad = &tc35893_data,
|
||||
.irq_base = MOP500_EGPIO_IRQ_BASE,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata mop500_i2c0_devices_u8500[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("tc3589x", 0x44),
|
||||
.platform_data = &tc3589x_keypad_data,
|
||||
.irq = NOMADIK_GPIO_TO_IRQ(218),
|
||||
.flags = I2C_CLIENT_WAKE,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
void __init mop500_u8500uib_init(void)
|
||||
{
|
||||
mop500_uib_i2c_add(3, mop500_i2c3_devices_u8500,
|
||||
ARRAY_SIZE(mop500_i2c3_devices_u8500));
|
||||
|
||||
mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500,
|
||||
ARRAY_SIZE(mop500_i2c0_devices_u8500));
|
||||
|
||||
}
|
135
arch/arm/mach-ux500/board-mop500-uib.c
Normal file
135
arch/arm/mach-ux500/board-mop500-uib.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
|
||||
* License terms: GNU General Public License (GPL), version 2
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "mop500-uib: " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include "board-mop500.h"
|
||||
|
||||
enum mop500_uib {
|
||||
STUIB,
|
||||
U8500UIB,
|
||||
};
|
||||
|
||||
struct uib {
|
||||
const char *name;
|
||||
const char *option;
|
||||
void (*init)(void);
|
||||
};
|
||||
|
||||
static struct __initdata uib mop500_uibs[] = {
|
||||
[STUIB] = {
|
||||
.name = "ST-UIB",
|
||||
.option = "stuib",
|
||||
.init = mop500_stuib_init,
|
||||
},
|
||||
[U8500UIB] = {
|
||||
.name = "U8500-UIB",
|
||||
.option = "u8500uib",
|
||||
.init = mop500_u8500uib_init,
|
||||
},
|
||||
};
|
||||
|
||||
static struct uib *mop500_uib;
|
||||
|
||||
static int __init mop500_uib_setup(char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mop500_uibs); i++) {
|
||||
struct uib *uib = &mop500_uibs[i];
|
||||
|
||||
if (!strcmp(str, uib->option)) {
|
||||
mop500_uib = uib;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(mop500_uibs))
|
||||
pr_err("invalid uib= option (%s)\n", str);
|
||||
|
||||
return 1;
|
||||
}
|
||||
__setup("uib=", mop500_uib_setup);
|
||||
|
||||
/*
|
||||
* The UIBs are detected after the I2C host controllers are registered, so
|
||||
* i2c_register_board_info() can't be used.
|
||||
*/
|
||||
void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
|
||||
unsigned n)
|
||||
{
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_client *client;
|
||||
int i;
|
||||
|
||||
adap = i2c_get_adapter(busnum);
|
||||
if (!adap) {
|
||||
pr_err("failed to get adapter i2c%d\n", busnum);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
client = i2c_new_device(adap, &info[i]);
|
||||
if (!client)
|
||||
pr_err("failed to register %s to i2c%d\n",
|
||||
info[i].type, busnum);
|
||||
}
|
||||
|
||||
i2c_put_adapter(adap);
|
||||
}
|
||||
|
||||
static void __init __mop500_uib_init(struct uib *uib, const char *why)
|
||||
{
|
||||
pr_info("%s (%s)\n", uib->name, why);
|
||||
uib->init();
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect the UIB attached based on the presence or absence of i2c devices.
|
||||
*/
|
||||
static int __init mop500_uib_init(void)
|
||||
{
|
||||
struct uib *uib = mop500_uib;
|
||||
struct i2c_adapter *i2c0;
|
||||
int ret;
|
||||
|
||||
if (!cpu_is_u8500())
|
||||
return -ENODEV;
|
||||
|
||||
if (uib) {
|
||||
__mop500_uib_init(uib, "from uib= boot argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
i2c0 = i2c_get_adapter(0);
|
||||
if (!i2c0) {
|
||||
__mop500_uib_init(&mop500_uibs[STUIB],
|
||||
"fallback, could not get i2c0");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */
|
||||
ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
|
||||
I2C_SMBUS_QUICK, NULL);
|
||||
i2c_put_adapter(i2c0);
|
||||
|
||||
if (ret == 0)
|
||||
uib = &mop500_uibs[U8500UIB];
|
||||
else
|
||||
uib = &mop500_uibs[STUIB];
|
||||
|
||||
__mop500_uib_init(uib, "detected");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(mop500_uib_init);
|
@ -17,68 +17,30 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/pl022.h>
|
||||
#include <linux/amba/serial.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/mfd/ab8500.h>
|
||||
#include <linux/mfd/tc3589x.h>
|
||||
#include <linux/leds-lp5521.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include <plat/pincfg.h>
|
||||
#include <plat/i2c.h>
|
||||
#include <plat/ste_dma40.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/setup.h>
|
||||
#include <mach/devices.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "ste-dma40-db8500.h"
|
||||
#include "devices-db8500.h"
|
||||
#include "pins-db8500.h"
|
||||
#include "board-mop500.h"
|
||||
#include "board-mop500-regulators.h"
|
||||
|
||||
static pin_cfg_t mop500_pins[] = {
|
||||
/* SSP0 */
|
||||
GPIO143_SSP0_CLK,
|
||||
GPIO144_SSP0_FRM,
|
||||
GPIO145_SSP0_RXD,
|
||||
GPIO146_SSP0_TXD,
|
||||
|
||||
/* I2C */
|
||||
GPIO147_I2C0_SCL,
|
||||
GPIO148_I2C0_SDA,
|
||||
GPIO16_I2C1_SCL,
|
||||
GPIO17_I2C1_SDA,
|
||||
GPIO10_I2C2_SDA,
|
||||
GPIO11_I2C2_SCL,
|
||||
GPIO229_I2C3_SDA,
|
||||
GPIO230_I2C3_SCL,
|
||||
|
||||
/* SKE keypad */
|
||||
GPIO153_KP_I7,
|
||||
GPIO154_KP_I6,
|
||||
GPIO155_KP_I5,
|
||||
GPIO156_KP_I4,
|
||||
GPIO157_KP_O7,
|
||||
GPIO158_KP_O6,
|
||||
GPIO159_KP_O5,
|
||||
GPIO160_KP_O4,
|
||||
GPIO161_KP_I3,
|
||||
GPIO162_KP_I2,
|
||||
GPIO163_KP_I1,
|
||||
GPIO164_KP_I0,
|
||||
GPIO165_KP_O3,
|
||||
GPIO166_KP_O2,
|
||||
GPIO167_KP_O1,
|
||||
GPIO168_KP_O0,
|
||||
|
||||
/* GPIO_EXP_INT */
|
||||
GPIO217_GPIO,
|
||||
|
||||
/* STMPE1601 IRQ */
|
||||
GPIO218_GPIO | PIN_INPUT_PULLUP,
|
||||
};
|
||||
|
||||
static struct ab8500_platform_data ab8500_platdata = {
|
||||
.irq_base = MOP500_AB8500_IRQ_BASE,
|
||||
.regulator = ab8500_regulators,
|
||||
@ -103,16 +65,6 @@ struct platform_device ab8500_device = {
|
||||
.resource = ab8500_resources,
|
||||
};
|
||||
|
||||
static struct pl022_ssp_controller ssp0_platform_data = {
|
||||
.bus_id = 0,
|
||||
/* pl022 not yet supports dma */
|
||||
.enable_dma = 0,
|
||||
/* on this platform, gpio 31,142,144,214 &
|
||||
* 224 are connected as chip selects
|
||||
*/
|
||||
.num_chipselect = 5,
|
||||
};
|
||||
|
||||
/*
|
||||
* TC35892
|
||||
*/
|
||||
@ -133,6 +85,56 @@ static struct tc3589x_platform_data mop500_tc35892_data = {
|
||||
.irq_base = MOP500_EGPIO_IRQ_BASE,
|
||||
};
|
||||
|
||||
static struct lp5521_led_config lp5521_pri_led[] = {
|
||||
[0] = {
|
||||
.chan_nr = 0,
|
||||
.led_current = 0x2f,
|
||||
.max_current = 0x5f,
|
||||
},
|
||||
[1] = {
|
||||
.chan_nr = 1,
|
||||
.led_current = 0x2f,
|
||||
.max_current = 0x5f,
|
||||
},
|
||||
[2] = {
|
||||
.chan_nr = 2,
|
||||
.led_current = 0x2f,
|
||||
.max_current = 0x5f,
|
||||
},
|
||||
};
|
||||
|
||||
static struct lp5521_platform_data __initdata lp5521_pri_data = {
|
||||
.label = "lp5521_pri",
|
||||
.led_config = &lp5521_pri_led[0],
|
||||
.num_channels = 3,
|
||||
.clock_mode = LP5521_CLOCK_EXT,
|
||||
};
|
||||
|
||||
static struct lp5521_led_config lp5521_sec_led[] = {
|
||||
[0] = {
|
||||
.chan_nr = 0,
|
||||
.led_current = 0x2f,
|
||||
.max_current = 0x5f,
|
||||
},
|
||||
[1] = {
|
||||
.chan_nr = 1,
|
||||
.led_current = 0x2f,
|
||||
.max_current = 0x5f,
|
||||
},
|
||||
[2] = {
|
||||
.chan_nr = 2,
|
||||
.led_current = 0x2f,
|
||||
.max_current = 0x5f,
|
||||
},
|
||||
};
|
||||
|
||||
static struct lp5521_platform_data __initdata lp5521_sec_data = {
|
||||
.label = "lp5521_sec",
|
||||
.led_config = &lp5521_sec_led[0],
|
||||
.num_channels = 3,
|
||||
.clock_mode = LP5521_CLOCK_EXT,
|
||||
};
|
||||
|
||||
static struct i2c_board_info mop500_i2c0_devices[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("tc3589x", 0x42),
|
||||
@ -141,6 +143,23 @@ static struct i2c_board_info mop500_i2c0_devices[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata mop500_i2c2_devices[] = {
|
||||
{
|
||||
/* lp5521 LED driver, 1st device */
|
||||
I2C_BOARD_INFO("lp5521", 0x33),
|
||||
.platform_data = &lp5521_pri_data,
|
||||
},
|
||||
{
|
||||
/* lp5521 LED driver, 2st device */
|
||||
I2C_BOARD_INFO("lp5521", 0x34),
|
||||
.platform_data = &lp5521_sec_data,
|
||||
},
|
||||
{
|
||||
/* Light sensor Rohm BH1780GLI */
|
||||
I2C_BOARD_INFO("bh1780", 0x29),
|
||||
},
|
||||
};
|
||||
|
||||
#define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
|
||||
static struct nmk_i2c_controller u8500_i2c##id##_data = { \
|
||||
/* \
|
||||
@ -178,8 +197,93 @@ static void __init mop500_i2c_init(void)
|
||||
db8500_add_i2c3(&u8500_i2c3_data);
|
||||
}
|
||||
|
||||
static struct gpio_keys_button mop500_gpio_keys[] = {
|
||||
{
|
||||
.desc = "SFH7741 Proximity Sensor",
|
||||
.type = EV_SW,
|
||||
.code = SW_FRONT_PROXIMITY,
|
||||
.active_low = 0,
|
||||
.can_disable = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static struct regulator *prox_regulator;
|
||||
static int mop500_prox_activate(struct device *dev);
|
||||
static void mop500_prox_deactivate(struct device *dev);
|
||||
|
||||
static struct gpio_keys_platform_data mop500_gpio_keys_data = {
|
||||
.buttons = mop500_gpio_keys,
|
||||
.nbuttons = ARRAY_SIZE(mop500_gpio_keys),
|
||||
.enable = mop500_prox_activate,
|
||||
.disable = mop500_prox_deactivate,
|
||||
};
|
||||
|
||||
static struct platform_device mop500_gpio_keys_device = {
|
||||
.name = "gpio-keys",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &mop500_gpio_keys_data,
|
||||
},
|
||||
};
|
||||
|
||||
static int mop500_prox_activate(struct device *dev)
|
||||
{
|
||||
prox_regulator = regulator_get(&mop500_gpio_keys_device.dev,
|
||||
"vcc");
|
||||
if (IS_ERR(prox_regulator)) {
|
||||
dev_err(&mop500_gpio_keys_device.dev,
|
||||
"no regulator\n");
|
||||
return PTR_ERR(prox_regulator);
|
||||
}
|
||||
regulator_enable(prox_regulator);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mop500_prox_deactivate(struct device *dev)
|
||||
{
|
||||
regulator_disable(prox_regulator);
|
||||
regulator_put(prox_regulator);
|
||||
}
|
||||
|
||||
/* add any platform devices here - TODO */
|
||||
static struct platform_device *platform_devs[] __initdata = {
|
||||
&mop500_gpio_keys_device,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
static struct stedma40_chan_cfg ssp0_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV8_SSP0_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg ssp0_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV8_SSP0_TX,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct pl022_ssp_controller ssp0_platform_data = {
|
||||
.bus_id = 0,
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.enable_dma = 1,
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &ssp0_dma_cfg_rx,
|
||||
.dma_tx_param = &ssp0_dma_cfg_tx,
|
||||
#else
|
||||
.enable_dma = 0,
|
||||
#endif
|
||||
/* on this platform, gpio 31,142,144,214 &
|
||||
* 224 are connected as chip selects
|
||||
*/
|
||||
.num_chipselect = 5,
|
||||
};
|
||||
|
||||
static void __init mop500_spi_init(void)
|
||||
@ -187,18 +291,108 @@ static void __init mop500_spi_init(void)
|
||||
db8500_add_ssp0(&ssp0_platform_data);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
static struct stedma40_chan_cfg uart0_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV13_UART0_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg uart0_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV13_UART0_TX,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg uart1_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV12_UART1_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg uart1_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV12_UART1_TX,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg uart2_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB8500_DMA_DEV11_UART2_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB8500_DMA_DEV11_UART2_TX,
|
||||
.src_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct amba_pl011_data uart0_plat = {
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &uart0_dma_cfg_rx,
|
||||
.dma_tx_param = &uart0_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct amba_pl011_data uart1_plat = {
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &uart1_dma_cfg_rx,
|
||||
.dma_tx_param = &uart1_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct amba_pl011_data uart2_plat = {
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &uart2_dma_cfg_rx,
|
||||
.dma_tx_param = &uart2_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void __init mop500_uart_init(void)
|
||||
{
|
||||
db8500_add_uart0();
|
||||
db8500_add_uart1();
|
||||
db8500_add_uart2();
|
||||
db8500_add_uart0(&uart0_plat);
|
||||
db8500_add_uart1(&uart1_plat);
|
||||
db8500_add_uart2(&uart2_plat);
|
||||
}
|
||||
|
||||
static void __init u8500_init_machine(void)
|
||||
static void __init mop500_init_machine(void)
|
||||
{
|
||||
/*
|
||||
* The HREFv60 board removed a GPIO expander and routed
|
||||
* all these GPIO pins to the internal GPIO controller
|
||||
* instead.
|
||||
*/
|
||||
if (machine_is_hrefv60())
|
||||
mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
|
||||
else
|
||||
mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
|
||||
|
||||
u8500_init_devices();
|
||||
|
||||
nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins));
|
||||
mop500_pins_init();
|
||||
|
||||
platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
|
||||
|
||||
@ -207,12 +401,12 @@ static void __init u8500_init_machine(void)
|
||||
mop500_spi_init();
|
||||
mop500_uart_init();
|
||||
|
||||
mop500_keypad_init();
|
||||
|
||||
platform_device_register(&ab8500_device);
|
||||
|
||||
i2c_register_board_info(0, mop500_i2c0_devices,
|
||||
ARRAY_SIZE(mop500_i2c0_devices));
|
||||
i2c_register_board_info(2, mop500_i2c2_devices,
|
||||
ARRAY_SIZE(mop500_i2c2_devices));
|
||||
}
|
||||
|
||||
MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
|
||||
@ -222,5 +416,13 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
|
||||
.init_irq = ux500_init_irq,
|
||||
/* we re-use nomadik timer here */
|
||||
.timer = &ux500_timer,
|
||||
.init_machine = u8500_init_machine,
|
||||
.init_machine = mop500_init_machine,
|
||||
MACHINE_END
|
||||
|
||||
MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
|
||||
.boot_params = 0x100,
|
||||
.map_io = u8500_map_io,
|
||||
.init_irq = ux500_init_irq,
|
||||
.timer = &ux500_timer,
|
||||
.init_machine = mop500_init_machine,
|
||||
MACHINE_END
|
||||
|
@ -7,15 +7,36 @@
|
||||
#ifndef __BOARD_MOP500_H
|
||||
#define __BOARD_MOP500_H
|
||||
|
||||
#define MOP500_EGPIO(x) (NOMADIK_NR_GPIO + (x))
|
||||
/* HREFv60-specific GPIO assignments, this board has no GPIO expander */
|
||||
#define HREFV60_TOUCH_RST_GPIO 143
|
||||
#define HREFV60_PROX_SENSE_GPIO 217
|
||||
#define HREFV60_HAL_SW_GPIO 145
|
||||
#define HREFV60_SDMMC_EN_GPIO 169
|
||||
#define HREFV60_SDMMC_1V8_3V_GPIO 5
|
||||
#define HREFV60_SDMMC_CD_GPIO 95
|
||||
#define HREFV60_ACCEL_INT1_GPIO 82
|
||||
#define HREFV60_ACCEL_INT2_GPIO 83
|
||||
#define HREFV60_MAGNET_DRDY_GPIO 32
|
||||
#define HREFV60_DISP1_RST_GPIO 65
|
||||
#define HREFV60_DISP2_RST_GPIO 66
|
||||
|
||||
/* GPIOs on the TC35892 expander */
|
||||
#define MOP500_EGPIO(x) (NOMADIK_NR_GPIO + (x))
|
||||
#define GPIO_SDMMC_CD MOP500_EGPIO(3)
|
||||
#define GPIO_PROX_SENSOR MOP500_EGPIO(7)
|
||||
#define GPIO_BU21013_CS MOP500_EGPIO(13)
|
||||
#define GPIO_SDMMC_EN MOP500_EGPIO(17)
|
||||
#define GPIO_SDMMC_1V8_3V_SEL MOP500_EGPIO(18)
|
||||
|
||||
struct i2c_board_info;
|
||||
|
||||
extern void mop500_sdi_init(void);
|
||||
extern void mop500_sdi_tc35892_init(void);
|
||||
extern void mop500_keypad_init(void);
|
||||
void __init mop500_u8500uib_init(void);
|
||||
void __init mop500_stuib_init(void);
|
||||
void __init mop500_pins_init(void);
|
||||
|
||||
void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
|
||||
unsigned n);
|
||||
|
||||
#endif
|
||||
|
@ -31,6 +31,26 @@ static pin_cfg_t u5500_sdi_pins[] = {
|
||||
GPIO14_MC0_CLK | PIN_DIR_OUTPUT | PIN_VAL_LOW,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
struct stedma40_chan_cfg u5500_sdi0_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
.src_dev_type = DB5500_DMA_DEV24_SDMMC0_RX,
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg u5500_sdi0_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = STEDMA40_MEM_TO_PERIPH,
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
|
||||
.dst_dev_type = DB5500_DMA_DEV24_SDMMC0_TX,
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct mmci_platform_data u5500_sdi0_data = {
|
||||
.ocr_mask = MMC_VDD_165_195,
|
||||
.f_max = 50000000,
|
||||
@ -39,6 +59,11 @@ static struct mmci_platform_data u5500_sdi0_data = {
|
||||
MMC_CAP_MMC_HIGHSPEED,
|
||||
.gpio_cd = -1,
|
||||
.gpio_wp = -1,
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &u5500_sdi0_dma_cfg_rx,
|
||||
.dma_tx_param = &u5500_sdi0_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
||||
|
||||
void __init u5500_sdi_init(void)
|
||||
|
@ -22,9 +22,9 @@
|
||||
|
||||
static void __init u5500_uart_init(void)
|
||||
{
|
||||
db5500_add_uart0();
|
||||
db5500_add_uart1();
|
||||
db5500_add_uart2();
|
||||
db5500_add_uart0(NULL);
|
||||
db5500_add_uart1(NULL);
|
||||
db5500_add_uart2(NULL);
|
||||
}
|
||||
|
||||
static void __init u5500_init_machine(void)
|
||||
|
@ -313,7 +313,7 @@ static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000);
|
||||
static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK);
|
||||
static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */
|
||||
static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000);
|
||||
static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 50000000);
|
||||
static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 100000000);
|
||||
static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK);
|
||||
static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK);
|
||||
static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK);
|
||||
@ -520,7 +520,7 @@ static struct clk_lookup u8500_ed_clks[] = {
|
||||
CLK(ssp0_ed, "ssp0", NULL),
|
||||
|
||||
/* Peripheral Cluster #5 */
|
||||
CLK(usb_ed, "musb_hdrc.0", "usb"),
|
||||
CLK(usb_ed, "musb-ux500.0", "usb"),
|
||||
|
||||
/* Peripheral Cluster #6 */
|
||||
CLK(dmc_ed, "dmc", NULL),
|
||||
@ -561,7 +561,7 @@ static struct clk_lookup u8500_v1_clks[] = {
|
||||
CLK(ssp0_v1, "ssp0", NULL),
|
||||
|
||||
/* Peripheral Cluster #5 */
|
||||
CLK(usb_v1, "musb_hdrc.0", "usb"),
|
||||
CLK(usb_v1, "musb-ux500.0", "usb"),
|
||||
|
||||
/* Peripheral Cluster #6 */
|
||||
CLK(mtu1_v1, "mtu1", NULL),
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/pmu.h>
|
||||
|
||||
#include <plat/gpio.h>
|
||||
|
||||
@ -18,8 +19,10 @@
|
||||
#include <mach/devices.h>
|
||||
#include <mach/setup.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/usb.h>
|
||||
|
||||
#include "devices-db5500.h"
|
||||
#include "ste-dma40-db5500.h"
|
||||
|
||||
static struct map_desc u5500_uart_io_desc[] __initdata = {
|
||||
__IO_DEV_DESC(U5500_UART0_BASE, SZ_4K),
|
||||
@ -43,6 +46,26 @@ static struct map_desc u5500_io_desc[] __initdata = {
|
||||
__IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
|
||||
};
|
||||
|
||||
static struct resource db5500_pmu_resources[] = {
|
||||
[0] = {
|
||||
.start = IRQ_DB5500_PMU0,
|
||||
.end = IRQ_DB5500_PMU0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_DB5500_PMU1,
|
||||
.end = IRQ_DB5500_PMU1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device db5500_pmu_device = {
|
||||
.name = "arm-pmu",
|
||||
.id = ARM_PMU_DEVICE_CPU,
|
||||
.num_resources = ARRAY_SIZE(db5500_pmu_resources),
|
||||
.resource = db5500_pmu_resources,
|
||||
};
|
||||
|
||||
static struct resource mbox0_resources[] = {
|
||||
{
|
||||
.name = "mbox_peer",
|
||||
@ -127,7 +150,8 @@ static struct platform_device mbox2_device = {
|
||||
.num_resources = ARRAY_SIZE(mbox2_resources),
|
||||
};
|
||||
|
||||
static struct platform_device *u5500_platform_devs[] __initdata = {
|
||||
static struct platform_device *db5500_platform_devs[] __initdata = {
|
||||
&db5500_pmu_device,
|
||||
&mbox0_device,
|
||||
&mbox1_device,
|
||||
&mbox2_device,
|
||||
@ -166,12 +190,35 @@ void __init u5500_map_io(void)
|
||||
iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc));
|
||||
}
|
||||
|
||||
static int usb_db5500_rx_dma_cfg[] = {
|
||||
DB5500_DMA_DEV4_USB_OTG_IEP_1_9,
|
||||
DB5500_DMA_DEV5_USB_OTG_IEP_2_10,
|
||||
DB5500_DMA_DEV6_USB_OTG_IEP_3_11,
|
||||
DB5500_DMA_DEV20_USB_OTG_IEP_4_12,
|
||||
DB5500_DMA_DEV21_USB_OTG_IEP_5_13,
|
||||
DB5500_DMA_DEV22_USB_OTG_IEP_6_14,
|
||||
DB5500_DMA_DEV23_USB_OTG_IEP_7_15,
|
||||
DB5500_DMA_DEV38_USB_OTG_IEP_8
|
||||
};
|
||||
|
||||
static int usb_db5500_tx_dma_cfg[] = {
|
||||
DB5500_DMA_DEV4_USB_OTG_OEP_1_9,
|
||||
DB5500_DMA_DEV5_USB_OTG_OEP_2_10,
|
||||
DB5500_DMA_DEV6_USB_OTG_OEP_3_11,
|
||||
DB5500_DMA_DEV20_USB_OTG_OEP_4_12,
|
||||
DB5500_DMA_DEV21_USB_OTG_OEP_5_13,
|
||||
DB5500_DMA_DEV22_USB_OTG_OEP_6_14,
|
||||
DB5500_DMA_DEV23_USB_OTG_OEP_7_15,
|
||||
DB5500_DMA_DEV38_USB_OTG_OEP_8
|
||||
};
|
||||
|
||||
void __init u5500_init_devices(void)
|
||||
{
|
||||
db5500_add_gpios();
|
||||
db5500_dma_init();
|
||||
db5500_add_rtc();
|
||||
db5500_add_usb(usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg);
|
||||
|
||||
platform_add_devices(u5500_platform_devs,
|
||||
ARRAY_SIZE(u5500_platform_devs));
|
||||
platform_add_devices(db5500_platform_devs,
|
||||
ARRAY_SIZE(db5500_platform_devs));
|
||||
}
|
||||
|
@ -23,8 +23,10 @@
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/setup.h>
|
||||
#include <mach/devices.h>
|
||||
#include <mach/usb.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 = {
|
||||
@ -154,6 +156,28 @@ static void __init db8500_add_gpios(void)
|
||||
IRQ_DB8500_GPIO0, &pdata);
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
/*
|
||||
* This function is called from the board init
|
||||
*/
|
||||
@ -164,6 +188,7 @@ void __init u8500_init_devices(void)
|
||||
|
||||
db8500_add_rtc();
|
||||
db8500_add_gpios();
|
||||
db8500_add_usb(usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
|
||||
|
||||
platform_device_register_simple("cpufreq-u8500", -1, NULL, 0);
|
||||
platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
|
||||
|
@ -139,6 +139,7 @@ void dbx500_add_gpios(resource_size_t *base, int num, int irq,
|
||||
for (i = 0; i < num; i++, first += 32, irq++) {
|
||||
pdata->first_gpio = first;
|
||||
pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first);
|
||||
pdata->num_gpio = 32;
|
||||
|
||||
dbx500_add_gpio(i, base[i], irq, pdata);
|
||||
}
|
||||
|
@ -42,10 +42,13 @@ dbx500_add_sdi(const char *name, resource_size_t base, int irq,
|
||||
return dbx500_add_amba_device(name, base, irq, pdata, 0);
|
||||
}
|
||||
|
||||
struct amba_pl011_data;
|
||||
|
||||
static inline struct amba_device *
|
||||
dbx500_add_uart(const char *name, resource_size_t base, int irq)
|
||||
dbx500_add_uart(const char *name, resource_size_t base, int irq,
|
||||
struct amba_pl011_data *pdata)
|
||||
{
|
||||
return dbx500_add_amba_device(name, base, irq, NULL, 0);
|
||||
return dbx500_add_amba_device(name, base, irq, pdata, 0);
|
||||
}
|
||||
|
||||
struct nmk_i2c_controller;
|
||||
|
@ -34,6 +34,9 @@
|
||||
#define db5500_add_rtc() \
|
||||
dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC);
|
||||
|
||||
#define db5500_add_usb(rx_cfg, tx_cfg) \
|
||||
ux500_add_usb(U5500_USBOTG_BASE, IRQ_DB5500_USBOTG, rx_cfg, tx_cfg)
|
||||
|
||||
#define db5500_add_sdi0(pdata) \
|
||||
dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata)
|
||||
#define db5500_add_sdi1(pdata) \
|
||||
@ -54,13 +57,13 @@
|
||||
#define db5500_add_spi3(pdata) \
|
||||
dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata)
|
||||
|
||||
#define db5500_add_uart0() \
|
||||
dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0)
|
||||
#define db5500_add_uart1() \
|
||||
dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1)
|
||||
#define db5500_add_uart2() \
|
||||
dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2)
|
||||
#define db5500_add_uart3() \
|
||||
dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3)
|
||||
#define db5500_add_uart0(plat) \
|
||||
dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0, plat)
|
||||
#define db5500_add_uart1(plat) \
|
||||
dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1, plat)
|
||||
#define db5500_add_uart2(plat) \
|
||||
dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2, plat)
|
||||
#define db5500_add_uart3(plat) \
|
||||
dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3, plat)
|
||||
|
||||
#endif
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/pl022.h>
|
||||
|
||||
#include <plat/ste_dma40.h>
|
||||
|
||||
@ -67,12 +68,72 @@ struct stedma40_chan_cfg dma40_memcpy_conf_log = {
|
||||
|
||||
/*
|
||||
* Mapping between destination event lines and physical device address.
|
||||
* The event line is tied to a device and therefor the address is constant.
|
||||
* The event line is tied to a device and therefore the address is constant.
|
||||
* When the address comes from a primecell it will be configured in runtime
|
||||
* and we set the address to -1 as a placeholder.
|
||||
*/
|
||||
static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV];
|
||||
static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = {
|
||||
/* MUSB - these will be runtime-reconfigured */
|
||||
[DB8500_DMA_DEV39_USB_OTG_OEP_8] = -1,
|
||||
[DB8500_DMA_DEV16_USB_OTG_OEP_7_15] = -1,
|
||||
[DB8500_DMA_DEV17_USB_OTG_OEP_6_14] = -1,
|
||||
[DB8500_DMA_DEV18_USB_OTG_OEP_5_13] = -1,
|
||||
[DB8500_DMA_DEV19_USB_OTG_OEP_4_12] = -1,
|
||||
[DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = -1,
|
||||
[DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = -1,
|
||||
[DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = -1,
|
||||
/* PrimeCells - run-time configured */
|
||||
[DB8500_DMA_DEV0_SPI0_TX] = -1,
|
||||
[DB8500_DMA_DEV1_SD_MMC0_TX] = -1,
|
||||
[DB8500_DMA_DEV2_SD_MMC1_TX] = -1,
|
||||
[DB8500_DMA_DEV3_SD_MMC2_TX] = -1,
|
||||
[DB8500_DMA_DEV8_SSP0_TX] = -1,
|
||||
[DB8500_DMA_DEV9_SSP1_TX] = -1,
|
||||
[DB8500_DMA_DEV11_UART2_TX] = -1,
|
||||
[DB8500_DMA_DEV12_UART1_TX] = -1,
|
||||
[DB8500_DMA_DEV13_UART0_TX] = -1,
|
||||
[DB8500_DMA_DEV28_SD_MM2_TX] = -1,
|
||||
[DB8500_DMA_DEV29_SD_MM0_TX] = -1,
|
||||
[DB8500_DMA_DEV32_SD_MM1_TX] = -1,
|
||||
[DB8500_DMA_DEV33_SPI2_TX] = -1,
|
||||
[DB8500_DMA_DEV35_SPI1_TX] = -1,
|
||||
[DB8500_DMA_DEV40_SPI3_TX] = -1,
|
||||
[DB8500_DMA_DEV41_SD_MM3_TX] = -1,
|
||||
[DB8500_DMA_DEV42_SD_MM4_TX] = -1,
|
||||
[DB8500_DMA_DEV43_SD_MM5_TX] = -1,
|
||||
};
|
||||
|
||||
/* Mapping between source event lines and physical device address */
|
||||
static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV];
|
||||
static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = {
|
||||
/* MUSB - these will be runtime-reconfigured */
|
||||
[DB8500_DMA_DEV39_USB_OTG_IEP_8] = -1,
|
||||
[DB8500_DMA_DEV16_USB_OTG_IEP_7_15] = -1,
|
||||
[DB8500_DMA_DEV17_USB_OTG_IEP_6_14] = -1,
|
||||
[DB8500_DMA_DEV18_USB_OTG_IEP_5_13] = -1,
|
||||
[DB8500_DMA_DEV19_USB_OTG_IEP_4_12] = -1,
|
||||
[DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = -1,
|
||||
[DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = -1,
|
||||
[DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = -1,
|
||||
/* PrimeCells */
|
||||
[DB8500_DMA_DEV0_SPI0_RX] = -1,
|
||||
[DB8500_DMA_DEV1_SD_MMC0_RX] = -1,
|
||||
[DB8500_DMA_DEV2_SD_MMC1_RX] = -1,
|
||||
[DB8500_DMA_DEV3_SD_MMC2_RX] = -1,
|
||||
[DB8500_DMA_DEV8_SSP0_RX] = -1,
|
||||
[DB8500_DMA_DEV9_SSP1_RX] = -1,
|
||||
[DB8500_DMA_DEV11_UART2_RX] = -1,
|
||||
[DB8500_DMA_DEV12_UART1_RX] = -1,
|
||||
[DB8500_DMA_DEV13_UART0_RX] = -1,
|
||||
[DB8500_DMA_DEV28_SD_MM2_RX] = -1,
|
||||
[DB8500_DMA_DEV29_SD_MM0_RX] = -1,
|
||||
[DB8500_DMA_DEV32_SD_MM1_RX] = -1,
|
||||
[DB8500_DMA_DEV33_SPI2_RX] = -1,
|
||||
[DB8500_DMA_DEV35_SPI1_RX] = -1,
|
||||
[DB8500_DMA_DEV40_SPI3_RX] = -1,
|
||||
[DB8500_DMA_DEV41_SD_MM3_RX] = -1,
|
||||
[DB8500_DMA_DEV42_SD_MM4_RX] = -1,
|
||||
[DB8500_DMA_DEV43_SD_MM5_RX] = -1,
|
||||
};
|
||||
|
||||
/* Reserved event lines for memcpy only */
|
||||
static int dma40_memcpy_event[] = {
|
||||
|
@ -61,6 +61,9 @@ db8500_add_ssp(const char *name, resource_size_t base, int irq,
|
||||
#define db8500_add_rtc() \
|
||||
dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC);
|
||||
|
||||
#define db8500_add_usb(rx_cfg, tx_cfg) \
|
||||
ux500_add_usb(U8500_USBOTG_BASE, IRQ_DB8500_USBOTG, rx_cfg, tx_cfg)
|
||||
|
||||
#define db8500_add_sdi0(pdata) \
|
||||
dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata)
|
||||
#define db8500_add_sdi1(pdata) \
|
||||
@ -88,11 +91,11 @@ db8500_add_ssp(const char *name, resource_size_t base, int irq,
|
||||
#define db8500_add_spi3(pdata) \
|
||||
dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata)
|
||||
|
||||
#define db8500_add_uart0() \
|
||||
dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0)
|
||||
#define db8500_add_uart1() \
|
||||
dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1)
|
||||
#define db8500_add_uart2() \
|
||||
dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2)
|
||||
#define db8500_add_uart0(pdata) \
|
||||
dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0, pdata)
|
||||
#define db8500_add_uart1(pdata) \
|
||||
dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1, pdata)
|
||||
#define db8500_add_uart2(pdata) \
|
||||
dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2, pdata)
|
||||
|
||||
#endif
|
||||
|
@ -73,11 +73,27 @@ static struct stedma40_chan_cfg dma40_memcpy_conf_log = {
|
||||
*/
|
||||
static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = {
|
||||
[DB5500_DMA_DEV24_SDMMC0_RX] = -1,
|
||||
[DB5500_DMA_DEV38_USB_OTG_IEP_8] = -1,
|
||||
[DB5500_DMA_DEV23_USB_OTG_IEP_7_15] = -1,
|
||||
[DB5500_DMA_DEV22_USB_OTG_IEP_6_14] = -1,
|
||||
[DB5500_DMA_DEV21_USB_OTG_IEP_5_13] = -1,
|
||||
[DB5500_DMA_DEV20_USB_OTG_IEP_4_12] = -1,
|
||||
[DB5500_DMA_DEV6_USB_OTG_IEP_3_11] = -1,
|
||||
[DB5500_DMA_DEV5_USB_OTG_IEP_2_10] = -1,
|
||||
[DB5500_DMA_DEV4_USB_OTG_IEP_1_9] = -1,
|
||||
};
|
||||
|
||||
/* Mapping between destination event lines and physical device address */
|
||||
static const dma_addr_t dma40_tx_map[DB5500_DMA_NR_DEV] = {
|
||||
[DB5500_DMA_DEV24_SDMMC0_TX] = -1,
|
||||
[DB5500_DMA_DEV38_USB_OTG_OEP_8] = -1,
|
||||
[DB5500_DMA_DEV23_USB_OTG_OEP_7_15] = -1,
|
||||
[DB5500_DMA_DEV22_USB_OTG_OEP_6_14] = -1,
|
||||
[DB5500_DMA_DEV21_USB_OTG_OEP_5_13] = -1,
|
||||
[DB5500_DMA_DEV20_USB_OTG_OEP_4_12] = -1,
|
||||
[DB5500_DMA_DEV6_USB_OTG_OEP_3_11] = -1,
|
||||
[DB5500_DMA_DEV5_USB_OTG_OEP_2_10] = -1,
|
||||
[DB5500_DMA_DEV4_USB_OTG_OEP_1_9] = -1,
|
||||
};
|
||||
|
||||
static int dma40_memcpy_event[] = {
|
||||
|
@ -50,7 +50,11 @@ static void flush(void)
|
||||
|
||||
static inline void arch_decomp_setup(void)
|
||||
{
|
||||
if (machine_is_u8500())
|
||||
/* Check in run time if we run on an U8500 or U5500 */
|
||||
if (machine_is_u8500() ||
|
||||
machine_is_svp8500v1() ||
|
||||
machine_is_svp8500v2() ||
|
||||
machine_is_hrefv60())
|
||||
ux500_uart_base = U8500_UART2_BASE;
|
||||
else if (machine_is_u5500())
|
||||
ux500_uart_base = U5500_UART0_BASE;
|
||||
|
25
arch/arm/mach-ux500/include/mach/usb.h
Normal file
25
arch/arm/mach-ux500/include/mach/usb.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2011
|
||||
*
|
||||
* Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*/
|
||||
#ifndef __ASM_ARCH_USB_H
|
||||
#define __ASM_ARCH_USB_H
|
||||
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
#define UX500_MUSB_DMA_NUM_RX_CHANNELS 8
|
||||
#define UX500_MUSB_DMA_NUM_TX_CHANNELS 8
|
||||
|
||||
struct ux500_musb_board_data {
|
||||
void **dma_rx_param_array;
|
||||
void **dma_tx_param_array;
|
||||
u32 num_rx_channels;
|
||||
u32 num_tx_channels;
|
||||
bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
|
||||
};
|
||||
|
||||
void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg,
|
||||
int *dma_tx_cfg);
|
||||
#endif
|
160
arch/arm/mach-ux500/usb.c
Normal file
160
arch/arm/mach-ux500/usb.c
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2011
|
||||
*
|
||||
* Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*/
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/usb/musb.h>
|
||||
#include <plat/ste_dma40.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/usb.h>
|
||||
|
||||
#define MUSB_DMA40_RX_CH { \
|
||||
.mode = STEDMA40_MODE_LOGICAL, \
|
||||
.dir = STEDMA40_PERIPH_TO_MEM, \
|
||||
.dst_dev_type = STEDMA40_DEV_DST_MEMORY, \
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH, \
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH, \
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_16, \
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_16, \
|
||||
}
|
||||
|
||||
#define MUSB_DMA40_TX_CH { \
|
||||
.mode = STEDMA40_MODE_LOGICAL, \
|
||||
.dir = STEDMA40_MEM_TO_PERIPH, \
|
||||
.src_dev_type = STEDMA40_DEV_SRC_MEMORY, \
|
||||
.src_info.data_width = STEDMA40_WORD_WIDTH, \
|
||||
.dst_info.data_width = STEDMA40_WORD_WIDTH, \
|
||||
.src_info.psize = STEDMA40_PSIZE_LOG_16, \
|
||||
.dst_info.psize = STEDMA40_PSIZE_LOG_16, \
|
||||
}
|
||||
|
||||
static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_CHANNELS]
|
||||
= {
|
||||
MUSB_DMA40_RX_CH,
|
||||
MUSB_DMA40_RX_CH,
|
||||
MUSB_DMA40_RX_CH,
|
||||
MUSB_DMA40_RX_CH,
|
||||
MUSB_DMA40_RX_CH,
|
||||
MUSB_DMA40_RX_CH,
|
||||
MUSB_DMA40_RX_CH,
|
||||
MUSB_DMA40_RX_CH
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg musb_dma_tx_ch[UX500_MUSB_DMA_NUM_TX_CHANNELS]
|
||||
= {
|
||||
MUSB_DMA40_TX_CH,
|
||||
MUSB_DMA40_TX_CH,
|
||||
MUSB_DMA40_TX_CH,
|
||||
MUSB_DMA40_TX_CH,
|
||||
MUSB_DMA40_TX_CH,
|
||||
MUSB_DMA40_TX_CH,
|
||||
MUSB_DMA40_TX_CH,
|
||||
MUSB_DMA40_TX_CH,
|
||||
};
|
||||
|
||||
static void *ux500_dma_rx_param_array[UX500_MUSB_DMA_NUM_RX_CHANNELS] = {
|
||||
&musb_dma_rx_ch[0],
|
||||
&musb_dma_rx_ch[1],
|
||||
&musb_dma_rx_ch[2],
|
||||
&musb_dma_rx_ch[3],
|
||||
&musb_dma_rx_ch[4],
|
||||
&musb_dma_rx_ch[5],
|
||||
&musb_dma_rx_ch[6],
|
||||
&musb_dma_rx_ch[7]
|
||||
};
|
||||
|
||||
static void *ux500_dma_tx_param_array[UX500_MUSB_DMA_NUM_TX_CHANNELS] = {
|
||||
&musb_dma_tx_ch[0],
|
||||
&musb_dma_tx_ch[1],
|
||||
&musb_dma_tx_ch[2],
|
||||
&musb_dma_tx_ch[3],
|
||||
&musb_dma_tx_ch[4],
|
||||
&musb_dma_tx_ch[5],
|
||||
&musb_dma_tx_ch[6],
|
||||
&musb_dma_tx_ch[7]
|
||||
};
|
||||
|
||||
static struct ux500_musb_board_data musb_board_data = {
|
||||
.dma_rx_param_array = ux500_dma_rx_param_array,
|
||||
.dma_tx_param_array = ux500_dma_tx_param_array,
|
||||
.num_rx_channels = UX500_MUSB_DMA_NUM_RX_CHANNELS,
|
||||
.num_tx_channels = UX500_MUSB_DMA_NUM_TX_CHANNELS,
|
||||
.dma_filter = stedma40_filter,
|
||||
};
|
||||
|
||||
static u64 ux500_musb_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct musb_hdrc_config musb_hdrc_config = {
|
||||
.multipoint = true,
|
||||
.dyn_fifo = true,
|
||||
.num_eps = 16,
|
||||
.ram_bits = 16,
|
||||
};
|
||||
|
||||
static struct musb_hdrc_platform_data musb_platform_data = {
|
||||
#if defined(CONFIG_USB_MUSB_OTG)
|
||||
.mode = MUSB_OTG,
|
||||
#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
|
||||
.mode = MUSB_PERIPHERAL,
|
||||
#else /* defined(CONFIG_USB_MUSB_HOST) */
|
||||
.mode = MUSB_HOST,
|
||||
#endif
|
||||
.config = &musb_hdrc_config,
|
||||
.board_data = &musb_board_data,
|
||||
};
|
||||
|
||||
static struct resource usb_resources[] = {
|
||||
[0] = {
|
||||
.name = "usb-mem",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
|
||||
[1] = {
|
||||
.name = "mc", /* hard-coded in musb */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device ux500_musb_device = {
|
||||
.name = "musb-ux500",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &musb_platform_data,
|
||||
.dma_mask = &ux500_musb_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(usb_resources),
|
||||
.resource = usb_resources,
|
||||
};
|
||||
|
||||
static inline void ux500_usb_dma_update_rx_ch_config(int *src_dev_type)
|
||||
{
|
||||
u32 idx;
|
||||
|
||||
for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_CHANNELS; idx++)
|
||||
musb_dma_rx_ch[idx].src_dev_type = src_dev_type[idx];
|
||||
}
|
||||
|
||||
static inline void ux500_usb_dma_update_tx_ch_config(int *dst_dev_type)
|
||||
{
|
||||
u32 idx;
|
||||
|
||||
for (idx = 0; idx < UX500_MUSB_DMA_NUM_TX_CHANNELS; idx++)
|
||||
musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx];
|
||||
}
|
||||
|
||||
void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg,
|
||||
int *dma_tx_cfg)
|
||||
{
|
||||
ux500_musb_device.resource[0].start = base;
|
||||
ux500_musb_device.resource[0].end = base + SZ_64K - 1;
|
||||
ux500_musb_device.resource[1].start = irq;
|
||||
ux500_musb_device.resource[1].end = irq;
|
||||
|
||||
ux500_usb_dma_update_rx_ch_config(dma_rx_cfg);
|
||||
ux500_usb_dma_update_tx_ch_config(dma_tx_cfg);
|
||||
|
||||
platform_device_register(&ux500_musb_device);
|
||||
}
|
@ -30,23 +30,39 @@
|
||||
/*
|
||||
* The GPIO module in the Nomadik family of Systems-on-Chip is an
|
||||
* AMBA device, managing 32 pins and alternate functions. The logic block
|
||||
* is currently only used in the Nomadik.
|
||||
* is currently used in the Nomadik and ux500.
|
||||
*
|
||||
* Symbols in this file are called "nmk_gpio" for "nomadik gpio"
|
||||
*/
|
||||
|
||||
#define NMK_GPIO_PER_CHIP 32
|
||||
|
||||
struct nmk_gpio_chip {
|
||||
struct gpio_chip chip;
|
||||
void __iomem *addr;
|
||||
struct clk *clk;
|
||||
unsigned int bank;
|
||||
unsigned int parent_irq;
|
||||
int secondary_parent_irq;
|
||||
u32 (*get_secondary_status)(unsigned int bank);
|
||||
void (*set_ioforce)(bool enable);
|
||||
spinlock_t lock;
|
||||
/* Keep track of configured edges */
|
||||
u32 edge_rising;
|
||||
u32 edge_falling;
|
||||
u32 real_wake;
|
||||
u32 rwimsc;
|
||||
u32 fwimsc;
|
||||
u32 slpm;
|
||||
};
|
||||
|
||||
static struct nmk_gpio_chip *
|
||||
nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)];
|
||||
|
||||
static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
|
||||
|
||||
#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips)
|
||||
|
||||
static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
|
||||
unsigned offset, int gpio_mode)
|
||||
{
|
||||
@ -118,8 +134,35 @@ static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
|
||||
__nmk_gpio_set_output(nmk_chip, offset, val);
|
||||
}
|
||||
|
||||
static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
|
||||
unsigned offset, int gpio_mode,
|
||||
bool glitch)
|
||||
{
|
||||
u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC);
|
||||
u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC);
|
||||
|
||||
if (glitch && nmk_chip->set_ioforce) {
|
||||
u32 bit = BIT(offset);
|
||||
|
||||
/* Prevent spurious wakeups */
|
||||
writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC);
|
||||
writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC);
|
||||
|
||||
nmk_chip->set_ioforce(true);
|
||||
}
|
||||
|
||||
__nmk_gpio_set_mode(nmk_chip, offset, gpio_mode);
|
||||
|
||||
if (glitch && nmk_chip->set_ioforce) {
|
||||
nmk_chip->set_ioforce(false);
|
||||
|
||||
writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC);
|
||||
writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC);
|
||||
}
|
||||
}
|
||||
|
||||
static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
|
||||
pin_cfg_t cfg, bool sleep)
|
||||
pin_cfg_t cfg, bool sleep, unsigned int *slpmregs)
|
||||
{
|
||||
static const char *afnames[] = {
|
||||
[NMK_GPIO_ALT_GPIO] = "GPIO",
|
||||
@ -144,6 +187,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
|
||||
int slpm = PIN_SLPM(cfg);
|
||||
int output = PIN_DIR(cfg);
|
||||
int val = PIN_VAL(cfg);
|
||||
bool glitch = af == NMK_GPIO_ALT_C;
|
||||
|
||||
dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
|
||||
pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
|
||||
@ -155,6 +199,8 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
|
||||
int slpm_output = PIN_SLPM_DIR(cfg);
|
||||
int slpm_val = PIN_SLPM_VAL(cfg);
|
||||
|
||||
af = NMK_GPIO_ALT_GPIO;
|
||||
|
||||
/*
|
||||
* The SLPM_* values are normal values + 1 to allow zero to
|
||||
* mean "same as normal".
|
||||
@ -180,8 +226,116 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
|
||||
__nmk_gpio_set_pull(nmk_chip, offset, pull);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've backed up the SLPM registers (glitch workaround), modify
|
||||
* the backups since they will be restored.
|
||||
*/
|
||||
if (slpmregs) {
|
||||
if (slpm == NMK_GPIO_SLPM_NOCHANGE)
|
||||
slpmregs[nmk_chip->bank] |= BIT(offset);
|
||||
else
|
||||
slpmregs[nmk_chip->bank] &= ~BIT(offset);
|
||||
} else
|
||||
__nmk_gpio_set_slpm(nmk_chip, offset, slpm);
|
||||
__nmk_gpio_set_mode(nmk_chip, offset, af);
|
||||
|
||||
__nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Safe sequence used to switch IOs between GPIO and Alternate-C mode:
|
||||
* - Save SLPM registers
|
||||
* - Set SLPM=0 for the IOs you want to switch and others to 1
|
||||
* - Configure the GPIO registers for the IOs that are being switched
|
||||
* - Set IOFORCE=1
|
||||
* - Modify the AFLSA/B registers for the IOs that are being switched
|
||||
* - Set IOFORCE=0
|
||||
* - Restore SLPM registers
|
||||
* - Any spurious wake up event during switch sequence to be ignored and
|
||||
* cleared
|
||||
*/
|
||||
static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_BANKS; i++) {
|
||||
struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
|
||||
unsigned int temp = slpm[i];
|
||||
|
||||
if (!chip)
|
||||
break;
|
||||
|
||||
slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
|
||||
writel(temp, chip->addr + NMK_GPIO_SLPC);
|
||||
}
|
||||
}
|
||||
|
||||
static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_BANKS; i++) {
|
||||
struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
|
||||
|
||||
if (!chip)
|
||||
break;
|
||||
|
||||
writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
|
||||
}
|
||||
}
|
||||
|
||||
static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
|
||||
{
|
||||
static unsigned int slpm[NUM_BANKS];
|
||||
unsigned long flags;
|
||||
bool glitch = false;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) {
|
||||
glitch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
|
||||
|
||||
if (glitch) {
|
||||
memset(slpm, 0xff, sizeof(slpm));
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
int pin = PIN_NUM(cfgs[i]);
|
||||
int offset = pin % NMK_GPIO_PER_CHIP;
|
||||
|
||||
if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C)
|
||||
slpm[pin / NMK_GPIO_PER_CHIP] &= ~BIT(offset);
|
||||
}
|
||||
|
||||
nmk_gpio_glitch_slpm_init(slpm);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
struct nmk_gpio_chip *nmk_chip;
|
||||
int pin = PIN_NUM(cfgs[i]);
|
||||
|
||||
nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(pin));
|
||||
if (!nmk_chip) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock(&nmk_chip->lock);
|
||||
__nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
|
||||
cfgs[i], sleep, glitch ? slpm : NULL);
|
||||
spin_unlock(&nmk_chip->lock);
|
||||
}
|
||||
|
||||
if (glitch)
|
||||
nmk_gpio_glitch_slpm_restore(slpm);
|
||||
|
||||
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,19 +354,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
|
||||
*/
|
||||
int nmk_config_pin(pin_cfg_t cfg, bool sleep)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip;
|
||||
int gpio = PIN_NUM(cfg);
|
||||
unsigned long flags;
|
||||
|
||||
nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
|
||||
if (!nmk_chip)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&nmk_chip->lock, flags);
|
||||
__nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep);
|
||||
spin_unlock_irqrestore(&nmk_chip->lock, flags);
|
||||
|
||||
return 0;
|
||||
return __nmk_config_pins(&cfg, 1, sleep);
|
||||
}
|
||||
EXPORT_SYMBOL(nmk_config_pin);
|
||||
|
||||
@ -226,31 +368,13 @@ EXPORT_SYMBOL(nmk_config_pin);
|
||||
*/
|
||||
int nmk_config_pins(pin_cfg_t *cfgs, int num)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ret = nmk_config_pin(cfgs[i], false);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return __nmk_config_pins(cfgs, num, false);
|
||||
}
|
||||
EXPORT_SYMBOL(nmk_config_pins);
|
||||
|
||||
int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ret = nmk_config_pin(cfgs[i], true);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return __nmk_config_pins(cfgs, num, true);
|
||||
}
|
||||
EXPORT_SYMBOL(nmk_config_pins_sleep);
|
||||
|
||||
@ -277,9 +401,13 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
|
||||
if (!nmk_chip)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&nmk_chip->lock, flags);
|
||||
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
|
||||
spin_lock(&nmk_chip->lock);
|
||||
|
||||
__nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode);
|
||||
spin_unlock_irqrestore(&nmk_chip->lock, flags);
|
||||
|
||||
spin_unlock(&nmk_chip->lock);
|
||||
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -314,6 +442,15 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
|
||||
}
|
||||
|
||||
/* Mode functions */
|
||||
/**
|
||||
* nmk_gpio_set_mode() - set the mux mode of a gpio pin
|
||||
* @gpio: pin number
|
||||
* @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A,
|
||||
* NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C
|
||||
*
|
||||
* Sets the mode of the specified pin to one of the alternate functions or
|
||||
* plain GPIO.
|
||||
*/
|
||||
int nmk_gpio_set_mode(int gpio, int gpio_mode)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip;
|
||||
@ -401,8 +538,20 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
|
||||
}
|
||||
}
|
||||
|
||||
static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which,
|
||||
bool enable)
|
||||
static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
|
||||
int gpio, bool on)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_U8500
|
||||
if (cpu_is_u8500v2()) {
|
||||
__nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base,
|
||||
on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
|
||||
: NMK_GPIO_SLPM_WAKEUP_DISABLE);
|
||||
}
|
||||
#endif
|
||||
__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
|
||||
}
|
||||
|
||||
static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
|
||||
{
|
||||
int gpio;
|
||||
struct nmk_gpio_chip *nmk_chip;
|
||||
@ -415,44 +564,58 @@ static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which,
|
||||
if (!nmk_chip)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&nmk_chip->lock, flags);
|
||||
__nmk_gpio_irq_modify(nmk_chip, gpio, which, enable);
|
||||
spin_unlock_irqrestore(&nmk_chip->lock, flags);
|
||||
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
|
||||
spin_lock(&nmk_chip->lock);
|
||||
|
||||
__nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable);
|
||||
|
||||
if (!(nmk_chip->real_wake & bitmask))
|
||||
__nmk_gpio_set_wake(nmk_chip, gpio, enable);
|
||||
|
||||
spin_unlock(&nmk_chip->lock);
|
||||
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nmk_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
nmk_gpio_irq_modify(d, NORMAL, false);
|
||||
nmk_gpio_irq_maskunmask(d, false);
|
||||
}
|
||||
|
||||
static void nmk_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
nmk_gpio_irq_modify(d, NORMAL, true);
|
||||
nmk_gpio_irq_maskunmask(d, true);
|
||||
}
|
||||
|
||||
static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
bool enabled = !(desc->status & IRQ_DISABLED);
|
||||
struct nmk_gpio_chip *nmk_chip;
|
||||
unsigned long flags;
|
||||
u32 bitmask;
|
||||
int gpio;
|
||||
|
||||
gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
|
||||
nmk_chip = irq_data_get_irq_chip_data(d);
|
||||
if (!nmk_chip)
|
||||
return -EINVAL;
|
||||
bitmask = nmk_gpio_get_bitmask(gpio);
|
||||
|
||||
spin_lock_irqsave(&nmk_chip->lock, flags);
|
||||
#ifdef CONFIG_ARCH_U8500
|
||||
if (cpu_is_u8500v2()) {
|
||||
__nmk_gpio_set_slpm(nmk_chip, gpio,
|
||||
on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
|
||||
: NMK_GPIO_SLPM_WAKEUP_DISABLE);
|
||||
}
|
||||
#endif
|
||||
__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
|
||||
spin_unlock_irqrestore(&nmk_chip->lock, flags);
|
||||
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
|
||||
spin_lock(&nmk_chip->lock);
|
||||
|
||||
if (!enabled)
|
||||
__nmk_gpio_set_wake(nmk_chip, gpio, on);
|
||||
|
||||
if (on)
|
||||
nmk_chip->real_wake |= bitmask;
|
||||
else
|
||||
nmk_chip->real_wake &= ~bitmask;
|
||||
|
||||
spin_unlock(&nmk_chip->lock);
|
||||
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -483,7 +646,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
if (enabled)
|
||||
__nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false);
|
||||
|
||||
if (wake)
|
||||
if (enabled || wake)
|
||||
__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false);
|
||||
|
||||
nmk_chip->edge_rising &= ~bitmask;
|
||||
@ -497,7 +660,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
if (enabled)
|
||||
__nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true);
|
||||
|
||||
if (wake)
|
||||
if (enabled || wake)
|
||||
__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
|
||||
|
||||
spin_unlock_irqrestore(&nmk_chip->lock, flags);
|
||||
@ -514,12 +677,11 @@ static struct irq_chip nmk_gpio_irq_chip = {
|
||||
.irq_set_wake = nmk_gpio_irq_set_wake,
|
||||
};
|
||||
|
||||
static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
|
||||
u32 status)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip;
|
||||
struct irq_chip *host_chip = get_irq_chip(irq);
|
||||
unsigned int gpio_irq;
|
||||
u32 pending;
|
||||
unsigned int first_irq;
|
||||
|
||||
if (host_chip->irq_mask_ack)
|
||||
@ -532,29 +694,56 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
|
||||
nmk_chip = get_irq_data(irq);
|
||||
first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
|
||||
while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) {
|
||||
gpio_irq = first_irq + __ffs(pending);
|
||||
generic_handle_irq(gpio_irq);
|
||||
while (status) {
|
||||
int bit = __ffs(status);
|
||||
|
||||
generic_handle_irq(first_irq + bit);
|
||||
status &= ~BIT(bit);
|
||||
}
|
||||
|
||||
host_chip->irq_unmask(&desc->irq_data);
|
||||
}
|
||||
|
||||
static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip = get_irq_data(irq);
|
||||
u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
|
||||
|
||||
__nmk_gpio_irq_handler(irq, desc, status);
|
||||
}
|
||||
|
||||
static void nmk_gpio_secondary_irq_handler(unsigned int irq,
|
||||
struct irq_desc *desc)
|
||||
{
|
||||
struct nmk_gpio_chip *nmk_chip = get_irq_data(irq);
|
||||
u32 status = nmk_chip->get_secondary_status(nmk_chip->bank);
|
||||
|
||||
__nmk_gpio_irq_handler(irq, desc, status);
|
||||
}
|
||||
|
||||
static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
|
||||
{
|
||||
unsigned int first_irq;
|
||||
int i;
|
||||
|
||||
first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
|
||||
for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) {
|
||||
for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) {
|
||||
set_irq_chip(i, &nmk_gpio_irq_chip);
|
||||
set_irq_handler(i, handle_edge_irq);
|
||||
set_irq_flags(i, IRQF_VALID);
|
||||
set_irq_chip_data(i, nmk_chip);
|
||||
set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
|
||||
}
|
||||
|
||||
set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
|
||||
set_irq_data(nmk_chip->parent_irq, nmk_chip);
|
||||
|
||||
if (nmk_chip->secondary_parent_irq >= 0) {
|
||||
set_irq_chained_handler(nmk_chip->secondary_parent_irq,
|
||||
nmk_gpio_secondary_irq_handler);
|
||||
set_irq_data(nmk_chip->secondary_parent_irq, nmk_chip);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -605,6 +794,97 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
{
|
||||
int mode;
|
||||
unsigned i;
|
||||
unsigned gpio = chip->base;
|
||||
int is_out;
|
||||
struct nmk_gpio_chip *nmk_chip =
|
||||
container_of(chip, struct nmk_gpio_chip, chip);
|
||||
const char *modes[] = {
|
||||
[NMK_GPIO_ALT_GPIO] = "gpio",
|
||||
[NMK_GPIO_ALT_A] = "altA",
|
||||
[NMK_GPIO_ALT_B] = "altB",
|
||||
[NMK_GPIO_ALT_C] = "altC",
|
||||
};
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++, gpio++) {
|
||||
const char *label = gpiochip_is_requested(chip, i);
|
||||
bool pull;
|
||||
u32 bit = 1 << i;
|
||||
|
||||
if (!label)
|
||||
continue;
|
||||
|
||||
is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit;
|
||||
pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
|
||||
mode = nmk_gpio_get_mode(gpio);
|
||||
seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
|
||||
gpio, label,
|
||||
is_out ? "out" : "in ",
|
||||
chip->get
|
||||
? (chip->get(chip, i) ? "hi" : "lo")
|
||||
: "? ",
|
||||
(mode < 0) ? "unknown" : modes[mode],
|
||||
pull ? "pull" : "none");
|
||||
|
||||
if (!is_out) {
|
||||
int irq = gpio_to_irq(gpio);
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
|
||||
/* This races with request_irq(), set_irq_type(),
|
||||
* and set_irq_wake() ... but those are "rare".
|
||||
*
|
||||
* More significantly, trigger type flags aren't
|
||||
* currently maintained by genirq.
|
||||
*/
|
||||
if (irq >= 0 && desc->action) {
|
||||
char *trigger;
|
||||
|
||||
switch (desc->status & IRQ_TYPE_SENSE_MASK) {
|
||||
case IRQ_TYPE_NONE:
|
||||
trigger = "(default)";
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
trigger = "edge-falling";
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
trigger = "edge-rising";
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
trigger = "edge-both";
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
trigger = "level-high";
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
trigger = "level-low";
|
||||
break;
|
||||
default:
|
||||
trigger = "?trigger?";
|
||||
break;
|
||||
}
|
||||
|
||||
seq_printf(s, " irq-%d %s%s",
|
||||
irq, trigger,
|
||||
(desc->status & IRQ_WAKEUP)
|
||||
? " wakeup" : "");
|
||||
}
|
||||
}
|
||||
|
||||
seq_printf(s, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#define nmk_gpio_dbg_show NULL
|
||||
#endif
|
||||
|
||||
/* This structure is replicated for each GPIO block allocated at probe time */
|
||||
static struct gpio_chip nmk_gpio_template = {
|
||||
.direction_input = nmk_gpio_make_input,
|
||||
@ -612,10 +892,64 @@ static struct gpio_chip nmk_gpio_template = {
|
||||
.direction_output = nmk_gpio_make_output,
|
||||
.set = nmk_gpio_set_output,
|
||||
.to_irq = nmk_gpio_to_irq,
|
||||
.ngpio = NMK_GPIO_PER_CHIP,
|
||||
.dbg_show = nmk_gpio_dbg_show,
|
||||
.can_sleep = 0,
|
||||
};
|
||||
|
||||
/*
|
||||
* Called from the suspend/resume path to only keep the real wakeup interrupts
|
||||
* (those that have had set_irq_wake() called on them) as wakeup interrupts,
|
||||
* and not the rest of the interrupts which we needed to have as wakeups for
|
||||
* cpuidle.
|
||||
*
|
||||
* PM ops are not used since this needs to be done at the end, after all the
|
||||
* other drivers are done with their suspend callbacks.
|
||||
*/
|
||||
void nmk_gpio_wakeups_suspend(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_BANKS; i++) {
|
||||
struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
|
||||
|
||||
if (!chip)
|
||||
break;
|
||||
|
||||
chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
|
||||
chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
|
||||
|
||||
writel(chip->rwimsc & chip->real_wake,
|
||||
chip->addr + NMK_GPIO_RWIMSC);
|
||||
writel(chip->fwimsc & chip->real_wake,
|
||||
chip->addr + NMK_GPIO_FWIMSC);
|
||||
|
||||
if (cpu_is_u8500v2()) {
|
||||
chip->slpm = readl(chip->addr + NMK_GPIO_SLPC);
|
||||
|
||||
/* 0 -> wakeup enable */
|
||||
writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nmk_gpio_wakeups_resume(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_BANKS; i++) {
|
||||
struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
|
||||
|
||||
if (!chip)
|
||||
break;
|
||||
|
||||
writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
|
||||
writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
|
||||
|
||||
if (cpu_is_u8500v2())
|
||||
writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit nmk_gpio_probe(struct platform_device *dev)
|
||||
{
|
||||
struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
|
||||
@ -623,6 +957,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
|
||||
struct gpio_chip *chip;
|
||||
struct resource *res;
|
||||
struct clk *clk;
|
||||
int secondary_irq;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
@ -641,6 +976,12 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
secondary_irq = platform_get_irq(dev, 1);
|
||||
if (secondary_irq >= 0 && !pdata->get_secondary_status) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (request_mem_region(res->start, resource_size(res),
|
||||
dev_name(&dev->dev)) == NULL) {
|
||||
ret = -EBUSY;
|
||||
@ -664,14 +1005,19 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
|
||||
* The virt address in nmk_chip->addr is in the nomadik register space,
|
||||
* so we can simply convert the resource address, without remapping
|
||||
*/
|
||||
nmk_chip->bank = dev->id;
|
||||
nmk_chip->clk = clk;
|
||||
nmk_chip->addr = io_p2v(res->start);
|
||||
nmk_chip->chip = nmk_gpio_template;
|
||||
nmk_chip->parent_irq = irq;
|
||||
nmk_chip->secondary_parent_irq = secondary_irq;
|
||||
nmk_chip->get_secondary_status = pdata->get_secondary_status;
|
||||
nmk_chip->set_ioforce = pdata->set_ioforce;
|
||||
spin_lock_init(&nmk_chip->lock);
|
||||
|
||||
chip = &nmk_chip->chip;
|
||||
chip->base = pdata->first_gpio;
|
||||
chip->ngpio = pdata->num_gpio;
|
||||
chip->label = pdata->name ?: dev_name(&dev->dev);
|
||||
chip->dev = &dev->dev;
|
||||
chip->owner = THIS_MODULE;
|
||||
@ -680,6 +1026,9 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
|
||||
|
||||
nmk_gpio_chips[nmk_chip->bank] = nmk_chip;
|
||||
platform_set_drvdata(dev, nmk_chip);
|
||||
|
||||
nmk_gpio_init_irq(nmk_chip);
|
||||
@ -707,8 +1056,6 @@ static struct platform_driver nmk_gpio_driver = {
|
||||
.name = "gpio",
|
||||
},
|
||||
.probe = nmk_gpio_probe,
|
||||
.suspend = NULL, /* to be done */
|
||||
.resume = NULL,
|
||||
};
|
||||
|
||||
static int __init nmk_gpio_init(void)
|
||||
|
@ -75,6 +75,9 @@ extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
|
||||
extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
|
||||
extern int nmk_gpio_get_mode(int gpio);
|
||||
|
||||
extern void nmk_gpio_wakeups_suspend(void);
|
||||
extern void nmk_gpio_wakeups_resume(void);
|
||||
|
||||
/*
|
||||
* Platform data to register a block: only the initial gpio/irq number.
|
||||
*/
|
||||
@ -82,6 +85,9 @@ struct nmk_gpio_platform_data {
|
||||
char *name;
|
||||
int first_gpio;
|
||||
int first_irq;
|
||||
int num_gpio;
|
||||
u32 (*get_secondary_status)(unsigned int bank);
|
||||
void (*set_ioforce)(bool enable);
|
||||
};
|
||||
|
||||
#endif /* __ASM_PLAT_GPIO_H */
|
||||
|
Loading…
Reference in New Issue
Block a user