Commit ce70cb2d authored by Kai Svahn's avatar Kai Svahn Committed by Tony Lindgren

ARM: OMAP: Merge board specific files from N800 tree

This patch merges board specific files from N800 tree.
Nokia has published the files at:

http://repository.maemo.org/pool/maemo3.0/free/source/
kernel-source-rx-34_2.6.18.orig.tar.gz
kernel-source-rx-34_2.6.18-osso29.diff.gz
Signed-off-by: default avatarKai Svahn <kai.svahn@nokia.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 1f716e8a
...@@ -55,3 +55,12 @@ config MACH_OMAP_APOLLON ...@@ -55,3 +55,12 @@ config MACH_OMAP_APOLLON
config MACH_OMAP_2430SDP config MACH_OMAP_2430SDP
bool "OMAP 2430 SDP board" bool "OMAP 2430 SDP board"
depends on ARCH_OMAP2 && ARCH_OMAP24XX depends on ARCH_OMAP2 && ARCH_OMAP24XX
config MACH_NOKIA_N800
bool "Nokia N800"
depends on ARCH_OMAP24XX
config MACH_OMAP2_TUSB6010
bool
depends on ARCH_OMAP2 && ARCH_OMAP2420
default y if MACH_NOKIA_N800
\ No newline at end of file
...@@ -16,4 +16,8 @@ obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o ...@@ -16,4 +16,8 @@ obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o
obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
obj-$(CONFIG_MACH_NOKIA_N800) += board-n800.o board-n800-flash.o \
board-n800-mmc.o board-n800-bt.o \
board-n800-audio.o board-n800-usb.o \
board-n800-dsp.o board-n800-pm.o
/*
* linux/arch/arm/mach-omap2/board-n800-audio.c
*
* Copyright (C) 2006 Nokia Corporation
* Contact: Juha Yrjola
* Jarkko Nikula <jarkko.nikula@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/spi/tsc2301.h>
#include <asm/io.h>
#include <asm/arch/eac.h>
#include "../plat-omap/dsp/dsp_common.h"
#if defined(CONFIG_SPI_TSC2301_AUDIO) && defined(CONFIG_SND_OMAP24XX_EAC)
#define AUDIO_ENABLED
static struct clk *sys_clkout2;
static struct clk *func96m_clk;
static struct device *eac_device;
static struct device *tsc2301_device;
static int enable_audio;
static int audio_ok;
static spinlock_t audio_lock;
/*
* Leaving EAC and sys_clkout2 pins multiplexed to those subsystems results
* in about 2 mA extra current leak when audios are powered down. The
* workaround is to multiplex them to protected mode (with pull-ups enabled)
* whenever audio is not being used.
*/
static int eac_mux_disabled = 0;
static int clkout2_mux_disabled = 0;
static u32 saved_mux[2];
static void n800_enable_eac_mux(void)
{
if (!eac_mux_disabled)
return;
__raw_writel(saved_mux[1], IO_ADDRESS(0x48000124));
eac_mux_disabled = 0;
}
static void n800_disable_eac_mux(void)
{
if (eac_mux_disabled) {
WARN_ON(eac_mux_disabled);
return;
}
saved_mux[1] = __raw_readl(IO_ADDRESS(0x48000124));
__raw_writel(0x1f1f1f1f, IO_ADDRESS(0x48000124));
eac_mux_disabled = 1;
}
static void n800_enable_clkout2_mux(void)
{
if (!clkout2_mux_disabled)
return;
__raw_writel(saved_mux[0], IO_ADDRESS(0x480000e8));
clkout2_mux_disabled = 0;
}
static void n800_disable_clkout2_mux(void)
{
u32 l;
if (clkout2_mux_disabled) {
WARN_ON(clkout2_mux_disabled);
return;
}
saved_mux[0] = __raw_readl(IO_ADDRESS(0x480000e8));
l = saved_mux[0] & ~0xff;
l |= 0x1f;
__raw_writel(l, IO_ADDRESS(0x480000e8));
clkout2_mux_disabled = 1;
}
static int n800_eac_enable_ext_clocks(struct device *dev)
{
BUG_ON(tsc2301_device == NULL);
n800_enable_eac_mux();
tsc2301_mixer_enable_mclk(tsc2301_device);
return 0;
}
static void n800_eac_disable_ext_clocks(struct device *dev)
{
BUG_ON(tsc2301_device == NULL);
tsc2301_mixer_disable_mclk(tsc2301_device);
n800_disable_eac_mux();
}
static int n800_audio_set_power(void *pdata, int dac, int adc)
{
BUG_ON(pdata != tsc2301_device);
tsc2301_mixer_set_power(tsc2301_device, dac, adc);
return 0;
}
static int n800_audio_register_controls(void *pdata, struct snd_card *card)
{
BUG_ON(pdata != tsc2301_device);
return tsc2301_mixer_register_controls(tsc2301_device, card);
}
static struct eac_codec n800_eac_codec = {
.mclk_src = EAC_MCLK_EXT_2x12288000,
.codec_mode = EAC_CODEC_I2S,
.codec_conf.i2s.polarity_changed_mode = 0,
.codec_conf.i2s.sync_delay_enable = 0,
.default_rate = 48000,
.set_power = n800_audio_set_power,
.register_controls = n800_audio_register_controls,
.short_name = "TSC2301",
};
static int n800_register_codec(void)
{
int r, do_enable = 0;
unsigned long flags;
n800_eac_codec.private_data = tsc2301_device;
r = eac_register_codec(eac_device, &n800_eac_codec);
if (r < 0)
return r;
spin_lock_irqsave(&audio_lock, flags);
audio_ok = 1;
if (enable_audio)
do_enable = 1;
spin_unlock_irqrestore(&audio_lock, flags);
if (do_enable)
eac_set_mode(eac_device, 1, 1);
return 0;
}
static void n800_unregister_codec(void)
{
audio_ok = 0;
eac_unregister_codec(eac_device);
eac_set_mode(eac_device, 0, 0);
}
static int n800_eac_init(struct device *dev)
{
int r;
BUG_ON(eac_device != NULL);
eac_device = dev;
if (tsc2301_device != NULL) {
r = n800_register_codec();
if (r < 0)
return r;
}
return 0;
}
static void n800_eac_cleanup(struct device *dev)
{
eac_device = NULL;
if (tsc2301_device != NULL)
n800_unregister_codec();
}
static int n800_codec_get_clocks(struct device *dev)
{
sys_clkout2 = clk_get(dev, "sys_clkout2");
if (IS_ERR(sys_clkout2)) {
dev_err(dev, "Could not get sys_clkout2\n");
return -ENODEV;
}
/* configure 12 MHz output on SYS_CLKOUT2. Therefore we must use
* 96 MHz as its parent in order to get 12 MHz */
func96m_clk = clk_get(dev, "func_96m_ck");
if (IS_ERR(func96m_clk)) {
dev_err(dev, "Could not get func 96M clock\n");
clk_put(sys_clkout2);
return -ENODEV;
}
clk_set_parent(sys_clkout2, func96m_clk);
clk_set_rate(sys_clkout2, 12000000);
return 0;
}
static void n800_codec_put_clocks(struct device *dev)
{
clk_put(func96m_clk);
clk_put(sys_clkout2);
}
static int n800_codec_enable_clock(struct device *dev)
{
n800_enable_clkout2_mux();
return clk_enable(sys_clkout2);
}
static void n800_codec_disable_clock(struct device *dev)
{
clk_disable(sys_clkout2);
n800_disable_clkout2_mux();
}
static int n800_codec_init(struct device *dev)
{
int r;
BUG_ON(tsc2301_device != NULL);
tsc2301_device = dev;
if ((r = n800_codec_get_clocks(dev)) < 0)
return r;
if (eac_device != NULL) {
r = n800_register_codec();
if (r < 0) {
n800_codec_put_clocks(dev);
return r;
}
}
return 0;
}
static void n800_codec_cleanup(struct device *dev)
{
tsc2301_device = NULL;
if (eac_device != NULL)
n800_unregister_codec();
n800_codec_put_clocks(dev);
}
static struct eac_platform_data n800_eac_data = {
.init = n800_eac_init,
.cleanup = n800_eac_cleanup,
.enable_ext_clocks = n800_eac_enable_ext_clocks,
.disable_ext_clocks = n800_eac_disable_ext_clocks,
};
static const struct tsc2301_mixer_gpio n800_mixer_gpios[] = {
{
.name = "Headset Amplifier",
.gpio = 1,
.deactivate_on_pd = 1,
}, {
.name = "Speaker Amplifier",
.gpio = 2,
.def_enable = 1,
.deactivate_on_pd = 1,
}, {
.name = "Headset Mic Select",
.gpio = 3,
}
};
static struct platform_device retu_headset_device = {
.name = "retu-headset",
.id = -1,
.dev = {
.release = NULL,
},
};
void __init n800_audio_init(struct tsc2301_platform_data *tc)
{
spin_lock_init(&audio_lock);
if (platform_device_register(&retu_headset_device) < 0)
return;
omap_init_eac(&n800_eac_data);
tc->pll_pdc = 7;
tc->pll_a = 7;
tc->pll_n = 9;
tc->pll_output = 1;
tc->mclk_ratio = TSC2301_MCLK_256xFS;
tc->i2s_sample_rate = TSC2301_I2S_SR_48000;
tc->i2s_format = TSC2301_I2S_FORMAT0;
tc->power_down_blocks = TSC2301_REG_PD_MISC_MOPD;
tc->mixer_gpios = n800_mixer_gpios;
tc->n_mixer_gpios = ARRAY_SIZE(n800_mixer_gpios);
tc->codec_init = n800_codec_init;
tc->codec_cleanup = n800_codec_cleanup;
tc->enable_clock = n800_codec_enable_clock;
tc->disable_clock = n800_codec_disable_clock;
}
#else
void __init n800_audio_init(void)
{
}
#endif
#ifdef CONFIG_OMAP_DSP
int n800_audio_enable(struct dsp_kfunc_device *kdev, int stage)
{
#ifdef AUDIO_ENABLED
unsigned long flags;
int do_enable = 0;
spin_lock_irqsave(&audio_lock, flags);
pr_debug("DSP power up request (audio codec %sinitialized)\n",
audio_ok ? "" : "not ");
if (enable_audio)
goto out;
enable_audio = 1;
if (audio_ok)
do_enable = 1;
out:
spin_unlock_irqrestore(&audio_lock, flags);
if (do_enable)
eac_set_mode(eac_device, 1, 1);
#endif
return 0;
}
int n800_audio_disable(struct dsp_kfunc_device *kdev, int stage)
{
#ifdef AUDIO_ENABLED
unsigned long flags;
int do_disable = 0;
spin_lock_irqsave(&audio_lock, flags);
pr_debug("DSP power down request (audio codec %sinitialized)\n",
audio_ok ? "" : "not ");
if (!enable_audio)
goto out;
enable_audio = 0;
if (audio_ok)
do_disable = 1;
out:
spin_unlock_irqrestore(&audio_lock, flags);
if (do_disable)
eac_set_mode(eac_device, 0, 0);
#endif
return 0;
}
#endif /* CONFIG_OMAP_DSP */
/*
* Nokia N800 platform-specific data for Bluetooth
*
* Copyright (C) 2005, 2006 Nokia Corporation
* Contact: Ville Tervo <ville.tervo@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <asm/arch/board.h>
static struct platform_device n800_bt_device = {
.name = "hci_h4p",
.id = -1,
.num_resources = 0,
};
void __init n800_bt_init(void)
{
const struct omap_bluetooth_config *bt_config;
bt_config = (void *) omap_get_config(OMAP_TAG_NOKIA_BT,
struct omap_bluetooth_config);
n800_bt_device.dev.platform_data = (void *) bt_config;
if (platform_device_register(&n800_bt_device) < 0)
BUG();
}
/*
* linux/arch/arm/mach-omap2/board-n800-dsp.c
*
* Copyright (C) 2006 Nokia Corporation.
*
* Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/board.h>
#include "../plat-omap/dsp/dsp_common.h"
#if defined(CONFIG_OMAP_DSP)
/*
* dsp peripheral device: AUDIO
*/
static struct dsp_kfunc_device n800_audio_device = {
.name = "audio",
.type = DSP_KFUNC_DEV_TYPE_AUDIO,
.enable = n800_audio_enable,
.disable = n800_audio_disable,
};
/*
* dsp peripheral device: TIMER
*/
static int dsp_timer_probe(struct dsp_kfunc_device *kdev)
{
char clockname[20];
strcpy(clockname, kdev->name);
strcat(clockname, "_fck");
kdev->fck = clk_get(NULL, clockname);
if (IS_ERR(kdev->fck)) {
printk(KERN_ERR "couldn't acquire %s\n", clockname);
return PTR_ERR(kdev->fck);
}
pr_debug("%s probed successfully\n", clockname);
strcpy(clockname, kdev->name);
strcat(clockname, "_ick");
kdev->ick = clk_get(NULL, clockname);
if (IS_ERR(kdev->ick)) {
printk(KERN_ERR "couldn't acquire %s\n", clockname);
goto fail;
}
pr_debug("%s probed successfully\n", clockname);
return 0;
fail:
clk_put(kdev->fck);
return PTR_ERR(kdev->ick);
}
static int dsp_timer_remove(struct dsp_kfunc_device *kdev)
{
clk_put(kdev->ick);
clk_put(kdev->fck);
pr_debug("%s removed successfully\n", kdev->name);
return 0;
}
static int dsp_timer_enable(struct dsp_kfunc_device *kdev, int stage)
{
pr_debug("%s enabled(%d)\n", kdev->name, stage);
mutex_lock(&kdev->lock);
if (kdev->enabled)
goto out;
kdev->enabled = 1;
clk_enable(kdev->fck);
clk_enable(kdev->ick);
out:
mutex_unlock(&kdev->lock);
return 0;
}
static int dsp_timer_disable(struct dsp_kfunc_device *kdev, int stage)
{
pr_debug("%s disabled(%d)\n", kdev->name, stage);
mutex_lock(&kdev->lock);
if (kdev->enabled == 0)
goto out;
kdev->enabled = 0;
clk_disable(kdev->ick);
clk_disable(kdev->fck);
out:
mutex_unlock(&kdev->lock);
return 0;
}
static struct dsp_kfunc_device n800_timer_device = {
.name = "gpt5",
.type = DSP_KFUNC_DEV_TYPE_COMMON,
.probe = dsp_timer_probe,
.remove = dsp_timer_remove,
.enable = dsp_timer_enable,
.disable = dsp_timer_disable,
};
static struct dsp_kfunc_device *n800_kfunc_dev[] = {
&n800_audio_device,
&n800_timer_device,
};
void __init n800_dsp_init(void)
{
int i, ret;
struct dsp_kfunc_device **p = n800_kfunc_dev;
for (i = 0; i < ARRAY_SIZE(n800_kfunc_dev); i++) {
ret = dsp_kfunc_device_register(p[i]);
if (ret) {
printk(KERN_ERR
"KFUNC device registration failed: %s\n",
p[i]->name);
}
}
}
#else
void __init n800_dsp_init(void) { }
#endif /* CONFIG_OMAP_DSP */
/*
* linux/arch/arm/mach-omap2/board-n800-flash.c
*
* Copyright (C) 2006 Nokia Corporation
* Author: Juha Yrjola
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <asm/mach/flash.h>
#include <linux/mtd/onenand_regs.h>
#include <asm/io.h>
#include <asm/arch/onenand.h>
#include <asm/arch/board.h>
#include <asm/arch/gpmc.h>
static struct mtd_partition n800_partitions[8];
static int n800_onenand_setup(void __iomem *);
static struct omap_onenand_platform_data n800_onenand_data = {
.cs = 0,
.gpio_irq = 26,
.parts = n800_partitions,
.nr_parts = 0, /* filled later */
.onenand_setup = n800_onenand_setup,
};
static struct platform_device n800_onenand_device = {
.name = "omap2-onenand",
.id = -1,
.dev = {
.platform_data = &n800_onenand_data,
},
};
static unsigned short omap2_onenand_readw(void __iomem *addr)
{
return readw(addr);
}
static void omap2_onenand_writew(unsigned short value, void __iomem *addr)
{
writew(value, addr);
}
static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base)
{
const int min_gpmc_clk_period = 18;
struct gpmc_timings t;
int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
u32 reg;
tick_ns = gpmc_round_ns_to_ticks(1);
div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
gpmc_clk_ns = div * tick_ns;
if (gpmc_clk_ns >= 24)
latency = 3;
else
latency = 4;
/* Configure OneNAND for sync read */
reg = omap2_onenand_readw(onenand_base + ONENAND_REG_SYS_CFG1);
reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
ONENAND_SYS_CFG1_SYNC_READ |
ONENAND_SYS_CFG1_BL_16;
omap2_onenand_writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
/* FIXME: Get timings from platform data */
/* Set syncronous read timings */
memset(&t, 0, sizeof(t));
t.sync_clk = min_gpmc_clk_period;
t.cs_on = 0;
t.adv_on = gpmc_round_ns_to_ticks(7);
fclk_offset_ns = t.adv_on + gpmc_round_ns_to_ticks(7);
fclk_offset = fclk_offset_ns / gpmc_round_ns_to_ticks(1);
t.page_burst_access = gpmc_clk_ns;
/* Read */
t.adv_rd_off = fclk_offset_ns + gpmc_round_ns_to_ticks(7);
t.oe_on = t.adv_rd_off;
t.access = fclk_offset_ns + (latency + 1) * gpmc_clk_ns;
t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
t.cs_rd_off = t.oe_off;
t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(17);
/* Write */
t.adv_wr_off = t.adv_on + gpmc_round_ns_to_ticks(12);
t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(1);
t.we_off = t.we_on + gpmc_round_ns_to_ticks(40);
t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(1);
t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(1);
/* Configure GPMC for synchronous read */
fclk_offset %= div;
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
GPMC_CONFIG1_WRAPBURST_SUPP |
GPMC_CONFIG1_READMULTIPLE_SUPP |
GPMC_CONFIG1_READTYPE_SYNC |
GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
GPMC_CONFIG1_PAGE_LEN(2) |
GPMC_CONFIG1_WAIT_READ_MON |
GPMC_CONFIG1_WAIT_PIN_SEL(0) |
GPMC_CONFIG1_DEVICESIZE_16 |
GPMC_CONFIG1_DEVICETYPE_NOR |
GPMC_CONFIG1_MUXADDDATA);
return gpmc_cs_set_timings(cs, &t);
}
static int n800_onenand_setup(void __iomem *onenand_base)
{
struct omap_onenand_platform_data *datap = &n800_onenand_data;
struct device *dev = &n800_onenand_device.dev;
/* Set sync timings in GPMC */
if (omap2_onenand_set_sync_mode(datap->cs, onenand_base) < 0) {
dev_err(dev, "Unable to set synchronous mode\n");
return -EINVAL;
}
return 0;
}
void __init n800_flash_init(void)
{
const struct omap_partition_config *part;
int i = 0;
while ((part = omap_get_nr_config(OMAP_TAG_PARTITION,
struct omap_partition_config, i)) != NULL) {
struct mtd_partition *mpart;
mpart = n800_partitions + i;
mpart->name = (char *) part->name;
mpart->size = part->size;
mpart->offset = part->offset;
mpart->mask_flags = part->mask_flags;
i++;
if (i == ARRAY_SIZE(n800_partitions)) {
printk(KERN_ERR "Too many partitions supplied\n");
return;
}
}
n800_onenand_data.nr_parts = i;
if (platform_device_register(&n800_onenand_device) < 0) {
printk(KERN_ERR "Unable to register OneNAND device\n");
return;
}
}
/*
* linux/arch/arm/mach-omap2/board-n800-mmc.c
*
* Copyright (C) 2006 Nokia Corporation
* Author: Juha Yrjola
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <asm/arch/mmc.h>
#include <asm/arch/menelaus.h>
#include <asm/arch/gpio.h>
#ifdef CONFIG_MMC_OMAP
static const int slot_switch_gpio = 96;
static const int slot1_wp_gpio = 23;
static const int slot2_wp_gpio = 8;
static int slot1_cover_closed;
static int slot2_cover_closed;
static struct device *mmc_device;
/*
* VMMC --> slot 1
* VDCDC3_APE, VMCS2_APE --> slot 2
* GPIO96 --> Menelaus GPIO2
*/
static int n800_mmc_switch_slot(struct device *dev, int slot)
{
#ifdef CONFIG_MMC_DEBUG
dev_dbg(dev, "Choose slot %d\n", slot + 1);
#endif
if (slot == 0)
omap_set_gpio_dataout(slot_switch_gpio, 0);
else
omap_set_gpio_dataout(slot_switch_gpio, 1);
return 0;
}
static int n800_mmc_set_power(struct device *dev, int slot, int power_on,
int vdd)
{
int mV;
#ifdef CONFIG_MMC_DEBUG
dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
power_on ? "on" : "off", vdd);
#endif
if (slot == 0) {
if (!power_on)
return menelaus_set_vmmc(0);
switch (1 << vdd) {
case MMC_VDD_33_34:
case MMC_VDD_32_33:
case MMC_VDD_31_32:
mV = 3100;
break;
case MMC_VDD_30_31:
mV = 3000;
break;
case MMC_VDD_28_29:
mV = 2800;
break;
case MMC_VDD_18_19:
mV = 1850;
break;
default:
BUG();
}
return menelaus_set_vmmc(mV);
} else {
if (!power_on)
return menelaus_set_vdcdc(3, 0);
switch (1 << vdd) {
case MMC_VDD_33_34:
case MMC_VDD_32_33:
mV = 3300;
break;
case MMC_VDD_30_31:
case MMC_VDD_29_30:
mV = 3000;
break;
case MMC_VDD_28_29:
case MMC_VDD_27_28:
mV = 2800;
break;
case MMC_VDD_24_25:
case MMC_VDD_23_24:
mV = 2400;
break;
case MMC_VDD_22_23:
case MMC_VDD_21_22:
mV = 2200;
break;
case MMC_VDD_20_21:
case MMC_VDD_19_20:
mV = 2000;
break;
case MMC_VDD_18_19:
case MMC_VDD_17_18:
mV = 1800;
break;
case MMC_VDD_150_155:
case MMC_VDD_145_150:
mV = 1500;
break;
default:
BUG();
}
return menelaus_set_vdcdc(3, mV);
}
return 0;
}
static int n800_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
{
int r;
#ifdef CONFIG_MMC_DEBUG
dev_dbg(dev, "Set slot %d bus mode %s\n", slot + 1,
bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
#endif
BUG_ON(slot != 0 && slot != 1);
slot++;
switch (bus_mode) {
case MMC_BUSMODE_OPENDRAIN:
r = menelaus_set_mmc_opendrain(slot, 1);
break;
case MMC_BUSMODE_PUSHPULL:
r = menelaus_set_mmc_opendrain(slot, 0);
break;
default:
BUG();
}
if (r != 0 && printk_ratelimit())
dev_err(dev, "MMC: unable to set bus mode for slot %d\n",
slot);
return r;
}
#if 0
static int n800_mmc_get_ro(struct device *dev, int slot)
{
int ro;
slot++;
if (slot == 1)
ro = omap_get_gpio_datain(slot1_wp_gpio);
else
ro = omap_get_gpio_datain(slot2_wp_gpio);
#ifdef CONFIG_MMC_DEBUG
dev_dbg(dev, "Get RO slot %d: %s\n",
slot, ro ? "read-only" : "read-write");
#endif
return ro;
}
#endif
static int n800_mmc_get_cover_state(struct device *dev, int slot)
{
slot++;
BUG_ON(slot != 1 && slot != 2);
if (slot == 1)
return slot1_cover_closed;
else
return slot2_cover_closed;
}
static void n800_mmc_callback(void *data, u8 card_mask)
{
if (card_mask & (1 << 1))
slot2_cover_closed = 0;
else
slot2_cover_closed = 1;
omap_mmc_notify_cover_event(mmc_device, 1, slot2_cover_closed);
}
void n800_mmc_slot1_cover_handler(void *arg, int state)
{
if (mmc_device == NULL)
return;
slot1_cover_closed = state;
omap_mmc_notify_cover_event(mmc_device, 0, state);
}
static int n800_mmc_late_init(struct device *dev)
{
int r;
mmc_device = dev;
r = menelaus_set_slot_sel(1);
if (r < 0)
return r;
r = menelaus_set_mmc_slot(1, 1, 0, 1);
if (r < 0)
return r;
r = menelaus_set_mmc_slot(2, 1, 0, 1);
if (r < 0)
return r;
r = menelaus_get_slot_pin_states();
if (r < 0)
return r;
if (r & (1 << 1))
slot2_cover_closed = 1;
else
slot2_cover_closed = 0;
r = menelaus_register_mmc_callback(n800_mmc_callback, NULL);
return r;
}
static void n800_mmc_cleanup(struct device *dev)
{
menelaus_unregister_mmc_callback();
}
static struct omap_mmc_platform_data n800_mmc_data = {
.enabled = 1,
.nr_slots = 2,
.wire4 = 1,
.switch_slot = n800_mmc_switch_slot,
.init = n800_mmc_late_init,
.cleanup = n800_mmc_cleanup,
.slots[0] = {
.set_power = n800_mmc_set_power,
.set_bus_mode = n800_mmc_set_bus_mode,
.get_ro = NULL,
.get_cover_state= n800_mmc_get_cover_state,
.ocr_mask = MMC_VDD_18_19 | MMC_VDD_28_29 | MMC_VDD_30_31 |
MMC_VDD_32_33 | MMC_VDD_33_34,
.name = "internal",
},
.slots[1] = {
.set_power = n800_mmc_set_power,
.set_bus_mode = n800_mmc_set_bus_mode,
.get_ro = NULL,
.get_cover_state= n800_mmc_get_cover_state,
.ocr_mask = MMC_VDD_150_155 | MMC_VDD_145_150 | MMC_VDD_17_18 |
MMC_VDD_18_19 | MMC_VDD_19_20 | MMC_VDD_20_21 |
MMC_VDD_21_22 | MMC_VDD_22_23 | MMC_VDD_23_24 |
MMC_VDD_24_25 | MMC_VDD_27_28 | MMC_VDD_28_29 |
MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_32_33 |
MMC_VDD_33_34,
.name = "external",
},
};
void __init n800_mmc_init(void)
{
omap_set_mmc_info(1, &n800_mmc_data);
if (omap_request_gpio(slot_switch_gpio) < 0)
BUG();
omap_set_gpio_dataout(slot_switch_gpio, 0);
omap_set_gpio_direction(slot_switch_gpio, 0);
if (omap_request_gpio(slot1_wp_gpio) < 0)
BUG();
if (omap_request_gpio(slot2_wp_gpio) < 0)
BUG();
omap_set_gpio_direction(slot1_wp_gpio, 1);
omap_set_gpio_direction(slot2_wp_gpio, 1);
}
#else
void __init n800_mmc_init(void)
{
}
void n800_mmc_slot1_cover_handler(void *arg, int state)
{
}
#endif
/*
* Nokia N800 PM code
*
* Copyright (C) 2006 Nokia Corporation
* Author: Amit Kucheria <amit.kucheria@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/arch/menelaus.h>
#ifdef CONFIG_MENELAUS
static int n800_auto_sleep_regulators(void)
{
u32 val;
int ret;
val = EN_VPLL_SLEEP | EN_VMMC_SLEEP \
| EN_VAUX_SLEEP | EN_VIO_SLEEP \
| EN_VMEM_SLEEP | EN_DC3_SLEEP \
| EN_VC_SLEEP | EN_DC2_SLEEP;
ret = menelaus_set_regulator_sleep(1, val);
if (ret < 0) {
printk(KERN_ERR "Could not set regulators to sleep on "
"menelaus: %u\n", ret);
return ret;
}
return 0;
}
static int n800_auto_voltage_scale(void)
{
int ret;
ret = menelaus_set_vcore_hw(1400, 1050);
if (ret < 0) {
printk(KERN_ERR "Could not set VCORE voltage on "
"menelaus: %u\n", ret);
return ret;
}
return 0;
}
static int n800_menelaus_init(struct device *dev)
{
int ret;
ret = n800_auto_voltage_scale();
if (ret < 0)
return ret;
ret = n800_auto_sleep_regulators();
if (ret < 0)
return ret;
return 0;
}
static struct menelaus_platform_data n800_menelaus_platform_data = {
.late_init = n800_menelaus_init,
};
void __init n800_pm_init(void)
{
menelaus_set_platform_data(&n800_menelaus_platform_data);
}
#else
void __init n800_pm_init(void)
{
}
#endif
/*
* linux/arch/arm/mach-omap2/board-n800-usb.c
*
* Copyright (C) 2006 Nokia Corporation
* Author: Juha Yrjola
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/usb/musb.h>
#include <asm/arch/gpmc.h>
#include <asm/arch/gpio.h>
#define TUSB_ASYNC_CS 1
#define TUSB_SYNC_CS 4
#define GPIO_TUSB_INT 58
#define GPIO_TUSB_ENABLE 0
static int tusb_set_power(int state);
#if defined(CONFIG_USB_MUSB_OTG)
# define BOARD_MODE MUSB_OTG
#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
# define BOARD_MODE MUSB_PERIPHERAL
#else /* defined(CONFIG_USB_MUSB_HOST) */
# define BOARD_MODE MUSB_HOST
#endif
static struct musb_hdrc_platform_data tusb_data = {
.mode = BOARD_MODE,
.multipoint = 1,
.set_power = tusb_set_power,
.min_power = 25, /* x2 = 50 mA drawn from VBUS as peripheral */
};
/*
* Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
* 1.5 V voltage regulators of PM companion chip. Companion chip will then
* provide then PGOOD signal to TUSB6010 which will release it from reset.
*/
static int tusb_set_power(int state)
{
int i, retval = 0;
if (state) {
omap_set_gpio_dataout(GPIO_TUSB_ENABLE, 1);
msleep(1);
/* Wait until TUSB6010 pulls INT pin down */
i = 100;
while (i && omap_get_gpio_datain(GPIO_TUSB_INT)) {
msleep(1);
i--;
}
if (!i) {
printk(KERN_ERR "tusb: powerup failed\n");
retval = -ENODEV;
}
} else {
omap_set_gpio_dataout(GPIO_TUSB_ENABLE, 0);
msleep(10);
}
return retval;
}
void __init n800_usb_init(void)
{
int ret = 0;
static char announce[] __initdata = KERN_INFO "TUSB 6010\n";
/* PM companion chip power control pin */
ret = omap_request_gpio(GPIO_TUSB_ENABLE);
if (ret != 0) {
printk(KERN_ERR "Could not get TUSB power GPIO%i\n",
GPIO_TUSB_ENABLE);
return;
}
omap_set_gpio_direction(GPIO_TUSB_ENABLE, 0);
tusb_set_power(0);
ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
TUSB_ASYNC_CS, TUSB_SYNC_CS,
GPIO_TUSB_INT, 0x3f);
if (ret != 0)
goto err;
printk(announce);
return;
err:
omap_free_gpio(GPIO_TUSB_ENABLE);
}
/*
* linux/arch/arm/mach-omap2/board-n800.c
*
* Copyright (C) 2005 Nokia Corporation
* Author: Juha Yrjola <juha.yrjola@nokia.com>
*
* Modified from mach-omap2/board-generic.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/tsc2301.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/arch/gpio.h>
#include <asm/arch/usb.h>
#include <asm/arch/board.h>
#include <asm/arch/common.h>
#include <asm/arch/mcspi.h>
#include <asm/arch/menelaus.h>
#include <asm/arch/lcd_mipid.h>
#include <asm/arch/clock.h>
#include <asm/arch/gpio-switch.h>
#include <asm/arch/omapfb.h>
#include <asm/arch/blizzard.h>
#include <../drivers/cbus/tahvo.h>
#define N800_BLIZZARD_POWERDOWN_GPIO 15
#define N800_STI_GPIO 62
#define N800_CAM_SENSOR_RESET_GPIO 53
#define N800_KEYB_IRQ_GPIO 109
static void __init nokia_n800_init_irq(void)
{
omap2_init_common_hw();
omap_init_irq();
omap_gpio_init();
#ifdef CONFIG_OMAP_STI
if (omap_request_gpio(N800_STI_GPIO) < 0) {
printk(KERN_ERR "Failed to request GPIO %d for STI\n",
N800_STI_GPIO);
return;
}
omap_set_gpio_direction(N800_STI_GPIO, 0);
omap_set_gpio_dataout(N800_STI_GPIO, 0);
#endif
}
#if defined(CONFIG_MENELAUS) && defined(CONFIG_SENSORS_TMP105)
static int n800_tmp105_set_power(int enable)
{
return menelaus_set_vaux(enable ? 2800 : 0);
}
#else
#define n800_tmp105_set_power NULL
#endif
static struct omap_uart_config n800_uart_config __initdata = {
.enabled_uarts = (1 << 0) | (1 << 2),
};
#include "../../../drivers/cbus/retu.h"
static struct omap_fbmem_config n800_fbmem0_config __initdata = {
.size = 752 * 1024,
};
static struct omap_fbmem_config n800_fbmem1_config __initdata = {
.size = 752 * 1024,
};
static struct omap_fbmem_config n800_fbmem2_config __initdata = {
.size = 752 * 1024,
};
static struct omap_tmp105_config n800_tmp105_config __initdata = {
.tmp105_irq_pin = 125,
.set_power = n800_tmp105_set_power,
};
static void mipid_shutdown(struct mipid_platform_data *pdata)
{
if (pdata->nreset_gpio != -1) {
pr_info("shutdown LCD\n");
omap_set_gpio_dataout(pdata->nreset_gpio, 0);
msleep(120);
}
}
static struct mipid_platform_data n800_mipid_platform_data = {
.shutdown = mipid_shutdown,
};
static void __init mipid_dev_init(void)
{
const struct omap_lcd_config *conf;
conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
if (conf != NULL) {
n800_mipid_platform_data.nreset_gpio = conf->nreset_gpio;
n800_mipid_platform_data.data_lines = conf->data_lines;
}
}
static struct {
struct clk *sys_ck;
} blizzard;
static int blizzard_get_clocks(void)
{
blizzard.sys_ck = clk_get(0, "osc_ck");
if (IS_ERR(blizzard.sys_ck)) {
printk(KERN_ERR "can't get Blizzard clock\n");
return PTR_ERR(blizzard.sys_ck);
}
return 0;
}
static unsigned long blizzard_get_clock_rate(struct device *dev)
{
return clk_get_rate(blizzard.sys_ck);
}
static void blizzard_enable_clocks(int enable)
{
if (enable)
clk_enable(blizzard.sys_ck);
else
clk_disable(blizzard.sys_ck);
}
static void blizzard_power_up(struct device *dev)
{
/* Vcore to 1.475V */
tahvo_set_clear_reg_bits(0x07, 0, 0xf);
msleep(10);
blizzard_enable_clocks(1);
omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 1);
}
static void blizzard_power_down(struct device *dev)
{
omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 0);
blizzard_enable_clocks(0);
/* Vcore to 1.005V */
tahvo_set_clear_reg_bits(0x07, 0xf, 0);
}
static struct blizzard_platform_data n800_blizzard_data = {
.power_up = blizzard_power_up,
.power_down = blizzard_power_down,
.get_clock_rate = blizzard_get_clock_rate,
.te_connected = 1,
};
static void __init blizzard_dev_init(void)
{
int r;
r = omap_request_gpio(N800_BLIZZARD_POWERDOWN_GPIO);
if (r < 0)
return;
omap_set_gpio_direction(N800_BLIZZARD_POWERDOWN_GPIO, 0);
omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 1);
blizzard_get_clocks();
omapfb_set_ctrl_platform_data(&n800_blizzard_data);
}
#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_VIDEO_CAMERA_SENSOR_TCM825X) && \
defined(CONFIG_MENELAUS)
#define SUPPORT_SENSOR
#endif
#ifdef SUPPORT_SENSOR
static int sensor_okay;
/*
* VSIM1 --> CAM_IOVDD --> IOVDD (1.8 V)
*/
static int tcm825x_sensor_power_on(void *data)
{
int ret;
if (!sensor_okay)
return -ENODEV;
/* Set VMEM to 1.5V and VIO to 2.5V */
ret = menelaus_set_vmem(1500);
if (ret < 0) {
/* Try once more, it seems the sensor power up causes
* some problems on the I2C bus. */
ret = menelaus_set_vmem(1500);
if (ret < 0)
return ret;
}
msleep(1);
ret = menelaus_set_vio(2500);
if (ret < 0)
return ret;
/* Set VSim1 on */
retu_write_reg(RETU_REG_CTRL_SET, 0x0080);
msleep(100);
omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 1);
msleep(1);
return 0;
}
static int tcm825x_sensor_power_off(void * data)
{
int ret;
omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 0);
msleep(1);
/* Set VSim1 off */
retu_write_reg(RETU_REG_CTRL_CLR, 0x0080);
msleep(1);
/* Set VIO_MODE to off */
ret = menelaus_set_vio(0);
if (ret < 0)
return ret;
msleep(1);
/* Set VMEM_MODE to off */
ret = menelaus_set_vmem(0);
if (ret < 0)
return ret;
msleep(1);
return 0;
}
static struct omap_camera_sensor_config n800_sensor_config = {
.power_on = tcm825x_sensor_power_on,
.power_off = tcm825x_sensor_power_off,
};
static void __init n800_cam_init(void)
{
int r;
r = omap_request_gpio(N800_CAM_SENSOR_RESET_GPIO);
if (r < 0)
return;
omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 0);
omap_set_gpio_direction(N800_CAM_SENSOR_RESET_GPIO, 0);
sensor_okay = 1;
}
#else
static inline void n800_cam_init(void) {}
#endif
static struct omap_board_config_kernel n800_config[] = {
{ OMAP_TAG_UART, &n800_uart_config },
#ifdef SUPPORT_SENSOR
{ OMAP_TAG_CAMERA_SENSOR, &n800_sensor_config },
#endif
{ OMAP_TAG_FBMEM, &n800_fbmem0_config },
{ OMAP_TAG_FBMEM, &n800_fbmem1_config },
{ OMAP_TAG_FBMEM, &n800_fbmem2_config },
{ OMAP_TAG_TMP105, &n800_tmp105_config },
};
static int n800_get_keyb_irq_state(struct device *dev)
{
return !omap_get_gpio_datain(N800_KEYB_IRQ_GPIO);
}
static struct tsc2301_platform_data tsc2301_config = {
.reset_gpio = 118,
.dav_gpio = 103,
.pen_int_gpio = 106,
.keymap = {
-1, /* Event for bit 0 */
KEY_UP, /* Event for bit 1 (up) */
KEY_F5, /* Event for bit 2 (home) */
-1, /* Event for bit 3 */
KEY_LEFT, /* Event for bit 4 (left) */
KEY_ENTER, /* Event for bit 5 (enter) */
KEY_RIGHT, /* Event for bit 6 (right) */
-1, /* Event for bit 7 */
KEY_ESC, /* Event for bit 8 (cycle) */
KEY_DOWN, /* Event for bit 9 (down) */
KEY_F4, /* Event for bit 10 (menu) */
-1, /* Event for bit 11 */
KEY_F8, /* Event for bit 12 (Zoom-) */
KEY_F6, /* Event for bit 13 (FS) */
KEY_F7, /* Event for bit 14 (Zoom+) */
-1, /* Event for bit 15 */
},
.kp_rep = 0,
.get_keyb_irq_state = n800_get_keyb_irq_state,
};
static void tsc2301_dev_init(void)
{
int gpio = N800_KEYB_IRQ_GPIO;
if (omap_request_gpio(gpio) < 0) {
printk(KERN_ERR "can't get KBIRQ GPIO\n");
return;
}
omap_set_gpio_direction(gpio, 1);
tsc2301_config.keyb_int = OMAP_GPIO_IRQ(gpio);
}
static struct omap2_mcspi_device_config tsc2301_mcspi_config = {
.turbo_mode = 0,
.single_channel = 1,
};
static struct omap2_mcspi_device_config mipid_mcspi_config = {
.turbo_mode = 0,
.single_channel = 1,
};
static struct omap2_mcspi_device_config cx3110x_mcspi_config = {
.turbo_mode = 0,
.single_channel = 1,
};
static struct spi_board_info n800_spi_board_info[] __initdata = {
[0] = {
.modalias = "lcd_mipid",
.bus_num = 1,
.chip_select = 1,
.max_speed_hz = 4000000,
.controller_data= &mipid_mcspi_config,
.platform_data = &n800_mipid_platform_data,
}, [1] = {
.modalias = "cx3110x",
.bus_num = 2,
.chip_select = 0,
.max_speed_hz = 48000000,
.controller_data= &cx3110x_mcspi_config,
}, [2] = {
.modalias = "tsc2301",
.bus_num = 1,
.chip_select = 0,
.max_speed_hz = 6000000,
.controller_data= &tsc2301_mcspi_config,
.platform_data = &tsc2301_config,
},
};
#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM)
void retu_keypad_led_set_power(struct omap_pwm_led_platform_data *self,
int on_off)
{
if (on_off) {
retu_write_reg(RETU_REG_CTRL_SET, 1 << 6);
msleep(2);
retu_write_reg(RETU_REG_CTRL_SET, 1 << 3);
} else {
retu_write_reg(RETU_REG_CTRL_CLR, (1 << 6) | (1 << 3));
}
}
static struct omap_pwm_led_platform_data n800_keypad_led_data = {
.name = "keypad",
.intensity_timer = 10,
.blink_timer = 9,
.set_power = retu_keypad_led_set_power,
};
static struct platform_device n800_keypad_led_device = {
.name = "omap_pwm_led",
.id = -1,
.dev = {
.platform_data = &n800_keypad_led_data,
},
};
#endif
#if defined(CONFIG_TOUCHSCREEN_TSC2301)
static void __init n800_ts_set_config(void)
{
const struct omap_lcd_config *conf;
conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
if (conf != NULL) {
if (strcmp(conf->panel_name, "lph8923") == 0) {
tsc2301_config.ts_x_plate_ohm = 180;
tsc2301_config.ts_hw_avg = 4;
tsc2301_config.ts_ignore_last = 1;
tsc2301_config.ts_max_pressure = 255;
tsc2301_config.ts_stab_time = 100;
} else if (strcmp(conf->panel_name, "ls041y3") == 0) {
tsc2301_config.ts_x_plate_ohm = 280;
tsc2301_config.ts_hw_avg = 16;
tsc2301_config.ts_touch_pressure= 215;
tsc2301_config.ts_max_pressure = 255;
tsc2301_config.ts_ignore_last = 1;
} else {
printk(KERN_ERR "Unknown panel type, set default "
"touchscreen configuration\n");
tsc2301_config.ts_x_plate_ohm = 200;
tsc2301_config.ts_stab_time = 100;
}
}
}
#else
static inline void n800_ts_set_config(void)
{
}
#endif
static struct omap_gpio_switch n800_gpio_switches[] __initdata = {
{
.name = "bat_cover",
.gpio = -1,
.debounce_rising = 100,
.debounce_falling = 0,
.notify = n800_mmc_slot1_cover_handler,
.notify_data = NULL,
}, {
.name = "headphone",
.gpio = -1,
.debounce_rising = 200,
.debounce_falling = 200,
}, {
.name = "cam_act",
.gpio = -1,
.debounce_rising = 200,
.debounce_falling = 200,
}, {
.name = "cam_turn",
.gpio = -1,
.debounce_rising = 100,
.debounce_falling = 100,
},
};
static struct platform_device *n800_devices[] __initdata = {
#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM)
&n800_keypad_led_device,
#endif
};
static void __init nokia_n800_init(void)
{
platform_add_devices(n800_devices, ARRAY_SIZE(n800_devices));
n800_flash_init();
n800_mmc_init();
n800_bt_init();
n800_audio_init(&tsc2301_config);
n800_dsp_init();
n800_usb_init();
n800_cam_init();
n800_ts_set_config();
spi_register_board_info(n800_spi_board_info,
ARRAY_SIZE(n800_spi_board_info));
omap_serial_init();
mipid_dev_init();
blizzard_dev_init();
tsc2301_dev_init();
omap_register_gpio_switches(n800_gpio_switches,
ARRAY_SIZE(n800_gpio_switches));
n800_pm_init();
}
static void __init nokia_n800_map_io(void)
{
omap_board_config = n800_config;
omap_board_config_size = ARRAY_SIZE(n800_config);
omap2_map_common_io();
}
MACHINE_START(NOKIA_N800, "Nokia N800")
.phys_io = 0x48000000,
.io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = nokia_n800_map_io,
.init_irq = nokia_n800_init_irq,
.init_machine = nokia_n800_init,
.timer = &omap_timer,
MACHINE_END
...@@ -11,12 +11,24 @@ ...@@ -11,12 +11,24 @@
#include <linux/types.h> #include <linux/types.h>
struct tsc2301_platform_data;
struct dsp_kfunc_device;
extern void n800_bt_init(void);
extern void n800_dsp_init(void);
extern void n800_flash_init(void);
extern void n800_mmc_init(void);
extern void n800_pm_init(void);
extern void n800_usb_init(void);
extern void n800_audio_init(struct tsc2301_platform_data *);
extern int n800_audio_enable(struct dsp_kfunc_device *kdev, int stage);
extern int n800_audio_disable(struct dsp_kfunc_device *kdev, int stage);
extern void n800_mmc_slot1_cover_handler(void *arg, int state);
#define OMAP_TAG_NOKIA_BT 0x4e01 #define OMAP_TAG_NOKIA_BT 0x4e01
#define OMAP_TAG_WLAN_CX3110X 0x4e02 #define OMAP_TAG_WLAN_CX3110X 0x4e02
#define OMAP_TAG_CBUS 0x4e03 #define OMAP_TAG_CBUS 0x4e03
#define OMAP_TAG_EM_ASIC_BB5 0x4e04 #define OMAP_TAG_EM_ASIC_BB5 0x4e04
#define BT_CHIP_CSR 1 #define BT_CHIP_CSR 1
#define BT_CHIP_TI 2 #define BT_CHIP_TI 2
......
...@@ -25,9 +25,12 @@ ...@@ -25,9 +25,12 @@
#define OMAP_TAG_FBMEM 0x4f08 #define OMAP_TAG_FBMEM 0x4f08
#define OMAP_TAG_STI_CONSOLE 0x4f09 #define OMAP_TAG_STI_CONSOLE 0x4f09
#define OMAP_TAG_CAMERA_SENSOR 0x4f0a #define OMAP_TAG_CAMERA_SENSOR 0x4f0a
#define OMAP_TAG_PARTITION 0x4f0b
#define OMAP_TAG_TEA5761 0x4f10
#define OMAP_TAG_TMP105 0x4f11
#define OMAP_TAG_BOOT_REASON 0x4f80 #define OMAP_TAG_BOOT_REASON 0x4f80
#define OMAP_TAG_FLASH_PART 0x4f81 #define OMAP_TAG_FLASH_PART_STR 0x4f81
#define OMAP_TAG_VERSION_STR 0x4f82 #define OMAP_TAG_VERSION_STR 0x4f82
struct omap_clock_config { struct omap_clock_config {
...@@ -139,8 +142,25 @@ struct omap_uart_config { ...@@ -139,8 +142,25 @@ struct omap_uart_config {
unsigned int enabled_uarts; unsigned int enabled_uarts;
}; };
struct omap_tea5761_config {
u16 enable_gpio;
};
/* This cannot be passed from the bootloader */
struct omap_tmp105_config {
u16 tmp105_irq_pin;
int (* set_power)(int enable);
};
struct omap_partition_config {
char name[16];
unsigned int size;
unsigned int offset;
/* same as in include/linux/mtd/partitions.h */
unsigned int mask_flags;
};
struct omap_flash_part_config { struct omap_flash_part_str_config {
char part_table[0]; char part_table[0];
}; };
......
...@@ -16,4 +16,5 @@ struct omap_onenand_platform_data { ...@@ -16,4 +16,5 @@ struct omap_onenand_platform_data {
int gpio_irq; int gpio_irq;
struct mtd_partition *parts; struct mtd_partition *parts;
int nr_parts; int nr_parts;
int (*onenand_setup)(void __iomem *);
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment