Commit 14b9b697 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 27446aff
......@@ -54,4 +54,13 @@ config MACH_OMAP_APOLLON
config MACH_OMAP_2430SDP
bool "OMAP 2430 SDP board"
depends on ARCH_OMAP2 && ARCH_OMAP24XX
\ No newline at end of file
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
obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.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);
}
This diff is collapsed.
......@@ -11,12 +11,24 @@
#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_WLAN_CX3110X 0x4e02
#define OMAP_TAG_CBUS 0x4e03
#define OMAP_TAG_EM_ASIC_BB5 0x4e04
#define BT_CHIP_CSR 1
#define BT_CHIP_TI 2
......
......@@ -25,9 +25,12 @@
#define OMAP_TAG_FBMEM 0x4f08
#define OMAP_TAG_STI_CONSOLE 0x4f09
#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_FLASH_PART 0x4f81
#define OMAP_TAG_FLASH_PART_STR 0x4f81
#define OMAP_TAG_VERSION_STR 0x4f82
struct omap_clock_config {
......@@ -139,8 +142,25 @@ struct omap_uart_config {
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];
};
......
......@@ -16,4 +16,5 @@ struct omap_onenand_platform_data {
int gpio_irq;
struct mtd_partition *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