Commit bb3cee2b authored by Linus Walleij's avatar Linus Walleij Committed by Russell King

[ARM] 5473/1: U300 core machine support

This adds core support for the ST-Ericsson U300 series
platforms: U300, U330, U335 and U365. Supports memory
mappings, interrupt controller, system timer (clocksource
and clockevents), and binds to the existing drivers for
the PrimeCells used in this design: PL190 (VIC), PL180
(MMC/SD host) and PL011 (UART). This is intented to serve
as starting point for our mainling work, more patches to
follow.
Signed-off-by: default avatarLinus Walleij <linus.walleij@stericsson.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent cd27e485
if ARCH_U300
menu "ST-Ericsson AB U300/U330/U335/U365 Platform"
comment "ST-Ericsson Mobile Platform Products"
config MACH_U300
bool "U300"
comment "ST-Ericsson U300/U330/U335/U365 Feature Selections"
choice
prompt "U300/U330/U335/U365 system type"
default MACH_U300_BS2X
---help---
You need to select the target system, i.e. the
U300/U330/U335/U365 board that you want to compile your kernel
for.
config MACH_U300_BS2X
bool "S26/S26/B25/B26 Test Products"
depends on MACH_U300
help
Select this if you're developing on the
S26/S25 test products. (Also works on
B26/B25 big boards.)
config MACH_U300_BS330
bool "S330/B330 Test Products"
depends on MACH_U300
help
Select this if you're developing on the
S330/B330 test products.
config MACH_U300_BS335
bool "S335/B335 Test Products"
depends on MACH_U300
help
Select this if you're developing on the
S335/B335 test products.
config MACH_U300_BS365
bool "S365/B365 Test Products"
depends on MACH_U300
help
Select this if you're developing on the
S365/B365 test products.
endchoice
choice
prompt "Memory configuration"
default MACH_U300_SINGLE_RAM
---help---
You have to config the kernel according to the physical memory
configuration.
config MACH_U300_SINGLE_RAM
bool "Single RAM"
help
Select this if you want support for Single RAM phones.
config MACH_U300_DUAL_RAM
bool "Dual RAM"
help
Select this if you want support for Dual RAM phones.
This is two RAM memorys on different EMIFs.
endchoice
config U300_DEBUG
bool "Debug support for U300"
depends on PM
help
Debug support for U300 in sysfs, procfs etc.
config MACH_U300_SEMI_IS_SHARED
bool "The SEMI is used by both the access and application side"
depends on MACH_U300
help
This makes it possible to use the SEMI (Shared External
Memory Interface) from both from access and application
side.
comment "All the settings below must match the bootloader's settings"
config MACH_U300_ACCESS_MEM_SIZE
int "Access CPU memory allocation"
range 7 25
depends on MACH_U300_SINGLE_RAM
default 13
help
How much memory in MiB that the Access side CPU has allocated
config MACH_U300_2MB_ALIGNMENT_FIX
bool "2MiB alignment fix"
depends on MACH_U300_SINGLE_RAM
default y
help
If yes and the Access side CPU has allocated an odd size in
MiB, this fix gives you one MiB extra that would otherwise be
lost due to Linux 2 MiB alignment policy.
endmenu
endif
#
# Makefile for the linux kernel, U300 machine.
#
obj-y := core.o clock.o timer.o gpio.o padmux.o
obj-m :=
obj-n :=
obj- :=
obj-$(CONFIG_ARCH_U300) += u300.o
obj-$(CONFIG_MMC) += mmc.o
This diff is collapsed.
/*
*
* arch-arm/mach-u300/include/mach/debug-macro.S
*
*
* Copyright (C) 2006-2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
* Debugging macro include header.
* Author: Linus Walleij <linus.walleij@stericsson.com>
*/
#include <mach/hardware.h>
.macro addruart,rx
/* If we move the adress using MMU, use this. */
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
ldreq \rx, = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
ldrne \rx, = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
orr \rx, \rx, #0x00003000
.endm
#include <asm/hardware/debug-pl01x.S>
/*
*
* arch-arm/mach-u300/include/mach/entry-macro.S
*
*
* Copyright (C) 2006-2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
* Low-level IRQ helper macros for ST-Ericsson U300
* Author: Linus Walleij <linus.walleij@stericsson.com>
*/
#include <mach/hardware.h>
#include <asm/hardware/vic.h>
.macro disable_fiq
.endm
.macro get_irqnr_preamble, base, tmp
.endm
.macro arch_ret_to_user, tmp1, tmp2
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
ldr \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON0_BASE
ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
mov \irqnr, #0
teq \irqstat, #0
bne 1002f
1001: ldr \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON1_BASE
ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
mov \irqnr, #32
teq \irqstat, #0
beq 1003f
1002: tst \irqstat, #1
bne 1003f
add \irqnr, \irqnr, #1
movs \irqstat, \irqstat, lsr #1
bne 1002b
1003: /* EQ will be set if no irqs pending */
.endm
/*
*
* arch/arm/mach-u300/include/mach/memory.h
*
*
* Copyright (C) 2007-2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
* Memory virtual/physical mapping constants.
* Author: Linus Walleij <linus.walleij@stericsson.com>
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
*/
#ifndef __MACH_MEMORY_H
#define __MACH_MEMORY_H
#ifdef CONFIG_MACH_U300_DUAL_RAM
#define PHYS_OFFSET UL(0x48000000)
#define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100)
#else
#ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
#define PHYS_OFFSET (0x28000000 + \
(CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
(CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
#else
#define PHYS_OFFSET (0x28000000 + \
(CONFIG_MACH_U300_ACCESS_MEM_SIZE + \
(CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
#endif
#define BOOT_PARAMS_OFFSET (0x28000000 + \
(CONFIG_MACH_U300_ACCESS_MEM_SIZE + \
(CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024 + 0x100)
#endif
/*
* We enable a real big DMA buffer if need be.
*/
#define CONSISTENT_DMA_SIZE SZ_4M
#endif
/*
*
* arch/arm/mach-u300/include/mach/platform.h
*
*
* Copyright (C) 2006-2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
* Basic platform init and mapping functions.
* Author: Linus Walleij <linus.walleij@stericsson.com>
*/
#ifndef __ASSEMBLY__
void u300_map_io(void);
void u300_init_irq(void);
void u300_init_devices(void);
extern struct sys_timer u300_timer;
#endif
/*
*
* arch/arm/mach-u300/include/mach/system.h
*
*
* Copyright (C) 2007-2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
* System shutdown and reset functions.
* Author: Linus Walleij <linus.walleij@stericsson.com>
*/
#include <mach/hardware.h>
#include <asm/io.h>
#include <asm/hardware/vic.h>
#include <asm/irq.h>
/* Forward declare this function from the watchdog */
void coh901327_watchdog_reset(void);
static inline void arch_idle(void)
{
cpu_do_idle();
}
static void arch_reset(char mode, const char *cmd)
{
switch (mode) {
case 's':
case 'h':
printk(KERN_CRIT "RESET: shutting down/rebooting system\n");
/* Disable interrupts */
local_irq_disable();
#ifdef CONFIG_COH901327_WATCHDOG
coh901327_watchdog_reset();
#endif
break;
default:
/* Do nothing */
break;
}
/* Wait for system do die/reset. */
while (1);
}
/*
*
* arch/arm/mach-u300/include/mach/timex.h
*
*
* Copyright (C) 2006-2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
* Platform tick rate definition.
* Author: Linus Walleij <linus.walleij@stericsson.com>
*/
#ifndef __MACH_TIMEX_H
#define __MACH_TIMEX_H
/* This is for the APP OS GP1 (General Purpose 1) timer */
#define CLOCK_TICK_RATE 1000000
#endif
/*
* arch/arm/mach-u300/include/mach/uncompress.h
*
* Copyright (C) 2003 ARM Limited
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define AMBA_UART_DR (*(volatile unsigned char *)0xc0013000)
#define AMBA_UART_LCRH (*(volatile unsigned char *)0xc001302C)
#define AMBA_UART_CR (*(volatile unsigned char *)0xc0013030)
#define AMBA_UART_FR (*(volatile unsigned char *)0xc0013018)
/*
* This does not append a newline
*/
static inline void putc(int c)
{
while (AMBA_UART_FR & (1 << 5))
barrier();
AMBA_UART_DR = c;
}
static inline void flush(void)
{
while (AMBA_UART_FR & (1 << 3))
barrier();
}
/*
* nothing to do
*/
#define arch_decomp_setup()
#define arch_decomp_wdog()
/*
*
* arch/arm/mach-u300/include/mach/vmalloc.h
*
*
* Copyright (C) 2006-2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
* Virtual memory allocations
* End must be above the I/O registers and on an even 2MiB boundary.
* Author: Linus Walleij <linus.walleij@stericsson.com>
*/
#define VMALLOC_END 0xfe800000
/*
*
* arch/arm/mach-u300/mmc.c
*
*
* Copyright (C) 2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
*
* Author: Linus Walleij <linus.walleij@stericsson.com>
* Author: Johan Lundin <johan.lundin@stericsson.com>
* 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 <asm/mach/mmc.h>
#include "mmc.h"
struct mmci_card_event {
struct input_dev *mmc_input;
int mmc_inserted;
struct work_struct workq;
struct mmc_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;
}
/*
* Here follows a large chunk of code which will only be enabled if you
* have both the AB3100 chip mounted and the MMC subsystem activated.
*/
static u32 mmc_translate_vdd(struct device *dev, unsigned int voltage)
{
int v;
/*
* MMC Spec:
* bit 7: 1.70 - 1.95V
* bit 8 - 14: 2.0 - 2.6V
* bit 15 - 23: 2.7 - 3.6V
*
* ab3100 voltages:
* 000 - 2.85V
* 001 - 2.75V
* 010 - 1.8V
* 011 - 1.5V
*/
switch (voltage) {
case 8:
v = 3;
break;
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
v = 1;
break;
case 16:
v = 1;
break;
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
v = 0;
break;
default:
v = 0;
break;
}
/* PL180 voltage register bits */
return v << 2;
}
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 ? "removed" : "inserted");
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;
int ret = 0;
mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL);
if (!mmci_card)
return -ENOMEM;
/* Nominally 2.85V on our platform */
mmci_card->mmc0_plat_data.ocr_mask = MMC_VDD_28_29;
mmci_card->mmc0_plat_data.translate_vdd = mmc_translate_vdd;
mmci_card->mmc0_plat_data.status = mmc_status;
mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data;
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);
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;
}
/*
*
* arch/arm/mach-u300/mmc.h
*
*
* Copyright (C) 2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
*
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
*/
#ifndef MMC_H
#define MMC_H
#include <linux/amba/bus.h>
int __devinit mmc_init(struct amba_device *adev);
#endif
This diff is collapsed.
/*
*
* arch/arm/mach-u300/u300.c
*
*
* Copyright (C) 2006-2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
* Platform machine definition.
* Author: Linus Walleij <linus.walleij@stericsson.com>
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/platform.h>
#include <mach/memory.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
static void __init u300_init_machine(void)
{
u300_init_devices();
}
#ifdef CONFIG_MACH_U300_BS2X
#define MACH_U300_STRING "Ericsson AB U300 S25/S26/B25/B26 Prototype Board"
#endif
#ifdef CONFIG_MACH_U300_BS330
#define MACH_U300_STRING "Ericsson AB U330 S330/B330 Prototype Board"
#endif
#ifdef CONFIG_MACH_U300_BS335
#define MACH_U300_STRING "Ericsson AB U335 S335/B335 Prototype Board"
#endif
#ifdef CONFIG_MACH_U300_BS365
#define MACH_U300_STRING "Ericsson AB U365 S365/B365 Prototype Board"
#endif
MACHINE_START(U300, MACH_U300_STRING)
/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
.phys_io = U300_AHB_PER_PHYS_BASE,
.io_pg_offst = ((U300_AHB_PER_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = BOOT_PARAMS_OFFSET,
.map_io = u300_map_io,
.init_irq = u300_init_irq,
.timer = &u300_timer,
.init_machine = u300_init_machine,
MACHINE_END
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