Initial commit; kernel source import

This commit is contained in:
Nathan
2025-04-06 23:50:55 -05:00
commit 25c6d769f4
45093 changed files with 18199410 additions and 0 deletions

View File

@@ -0,0 +1,498 @@
# arch/arm/plat-samsung/Kconfig
#
# Copyright 2009 Simtec Electronics
#
# Licensed under GPLv2
config PLAT_SAMSUNG
bool
depends on PLAT_S3C24XX || ARCH_S3C64XX || PLAT_S5P
default y
select GENERIC_IRQ_CHIP
select NO_IOPORT
help
Base platform code for all Samsung SoC based systems
config PLAT_S5P
bool
depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
default y
select ARCH_REQUIRE_GPIOLIB
select ARM_GIC if ARCH_EXYNOS
select ARM_VIC if !ARCH_EXYNOS
select GIC_NON_BANKED if ARCH_EXYNOS4
select NO_IOPORT
select PLAT_SAMSUNG
select S3C_GPIO_TRACK
select S5P_GPIO_DRVSTR
select SAMSUNG_CLKSRC if !COMMON_CLK
select SAMSUNG_GPIOLIB_4BIT
select SAMSUNG_IRQ_VIC_TIMER
help
Base platform code for Samsung's S5P series SoC.
if PLAT_SAMSUNG
# boot configurations
comment "Boot options"
config S3C_BOOT_ERROR_RESET
bool "S3C Reboot on decompression error"
help
Say y here to use the watchdog to reset the system if the
kernel decompressor detects an error during decompression.
config S3C_BOOT_UART_FORCE_FIFO
bool "Force UART FIFO on during boot process"
default y
help
Say Y here to force the UART FIFOs on during the kernel
uncompressor
config S3C_LOWLEVEL_UART_PORT
int "S3C UART to use for low-level messages"
default 0
help
Choice of which UART port to use for the low-level messages,
such as the `Uncompressing...` at start time. The value of
this configuration should be between zero and two. The port
must have been initialised by the boot-loader before use.
# timer options
config SAMSUNG_HRT
bool
select SAMSUNG_DEV_PWM
help
Use the High Resolution timer support
# clock options
config SAMSUNG_CLOCK
bool
default y if !COMMON_CLK
config SAMSUNG_CLKSRC
bool
help
Select the clock code for the clksrc implementation
used by newer systems such as the S3C64XX.
config S5P_CLOCK
def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
help
Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
# options for IRQ support
config SAMSUNG_IRQ_VIC_TIMER
bool
help
Internal configuration to build the VIC timer interrupt code.
config S5P_IRQ
def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
help
Support common interrupt part for ARCH_S5P SoCs
config S5P_EXT_INT
bool
help
Use the external interrupts (other than GPIO interrupts.)
Note: Do not choose this for S5P6440 and S5P6450.
config S5P_GPIO_INT
bool
help
Common code for the GPIO interrupts (other than external interrupts.)
# options for gpio configuration support
config SAMSUNG_GPIOLIB_4BIT
bool
help
GPIOlib file contains the 4 bit modification functions for gpio
configuration. GPIOlib shall be compiled only for S3C64XX and S5P
series of processors.
config S5P_GPIO_DRVSTR
bool
help
Internal configuration to get and set correct GPIO driver strength
helper
config SAMSUNG_GPIO_EXTRA
int "Number of additional GPIO pins"
default 128 if SAMSUNG_GPIO_EXTRA128
default 64 if SAMSUNG_GPIO_EXTRA64
default 0
help
Use additional GPIO space in addition to the GPIO's the SOC
provides. This allows expanding the GPIO space for use with
GPIO expanders.
config SAMSUNG_GPIO_EXTRA64
bool
config SAMSUNG_GPIO_EXTRA128
bool
config S3C_GPIO_SPACE
int "Space between gpio banks"
default 0
help
Add a number of spare GPIO entries between each bank for debugging
purposes. This allows any problems where an counter overflows from
one bank to another to be caught, at the expense of using a little
more memory.
config S3C_GPIO_TRACK
bool
help
Internal configuration option to enable the s3c specific gpio
chip tracking if the platform requires it.
# uart options
config S5P_DEV_UART
def_bool y
depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
# ADC driver
config S3C_ADC
bool "ADC common driver support"
help
Core support for the ADC block found in the Samsung SoC systems
for drivers such as the touchscreen and hwmon to use to share
this resource.
# device definitions to compile in
config S3C_DEV_HSMMC
bool
help
Compile in platform device definitions for HSMMC code
config S3C_DEV_HSMMC1
bool
help
Compile in platform device definitions for HSMMC channel 1
config S3C_DEV_HSMMC2
bool
help
Compile in platform device definitions for HSMMC channel 2
config S3C_DEV_HSMMC3
bool
help
Compile in platform device definitions for HSMMC channel 3
config S3C_DEV_HWMON
bool
help
Compile in platform device definitions for HWMON
config S3C_DEV_I2C1
bool
help
Compile in platform device definitions for I2C channel 1
config S3C_DEV_I2C2
bool
help
Compile in platform device definitions for I2C channel 2
config S3C_DEV_I2C3
bool
help
Compile in platform device definition for I2C controller 3
config S3C_DEV_I2C4
bool
help
Compile in platform device definition for I2C controller 4
config S3C_DEV_I2C5
bool
help
Compile in platform device definition for I2C controller 5
config S3C_DEV_I2C6
bool
help
Compile in platform device definition for I2C controller 6
config S3C_DEV_I2C7
bool
help
Compile in platform device definition for I2C controller 7
config S3C_DEV_FB
bool
help
Compile in platform device definition for framebuffer
config S3C_DEV_USB_HOST
bool
help
Compile in platform device definition for USB host.
config S3C_DEV_USB_HSOTG
bool
help
Compile in platform device definition for USB high-speed OtG
config S3C_DEV_WDT
bool
default y if ARCH_S3C24XX
help
Complie in platform device definition for Watchdog Timer
config S3C_DEV_NAND
bool
help
Compile in platform device definition for NAND controller
config S3C_DEV_ONENAND
bool
help
Compile in platform device definition for OneNAND controller
config S3C_DEV_RTC
bool
help
Complie in platform device definition for RTC
config SAMSUNG_DEV_ADC
bool
help
Compile in platform device definition for ADC controller
config SAMSUNG_DEV_IDE
bool
help
Compile in platform device definitions for IDE
config S3C64XX_DEV_SPI0
bool
help
Compile in platform device definitions for S3C64XX's type
SPI controller 0
config S3C64XX_DEV_SPI1
bool
help
Compile in platform device definitions for S3C64XX's type
SPI controller 1
config S3C64XX_DEV_SPI2
bool
help
Compile in platform device definitions for S3C64XX's type
SPI controller 2
config SAMSUNG_DEV_TS
bool
help
Common in platform device definitions for touchscreen device
config SAMSUNG_DEV_KEYPAD
bool
help
Compile in platform device definitions for keypad
config SAMSUNG_DEV_PWM
bool
default y if ARCH_S3C24XX
help
Compile in platform device definition for PWM Timer
config SAMSUNG_DEV_BACKLIGHT
bool
depends on SAMSUNG_DEV_PWM
help
Compile in platform device definition LCD backlight with PWM Timer
config S5P_DEV_CSIS0
bool
help
Compile in platform device definitions for MIPI-CSIS channel 0
config S5P_DEV_CSIS1
bool
help
Compile in platform device definitions for MIPI-CSIS channel 1
config S5P_DEV_FIMC0
bool
help
Compile in platform device definitions for FIMC controller 0
config S5P_DEV_FIMC1
bool
help
Compile in platform device definitions for FIMC controller 1
config S5P_DEV_FIMC2
bool
help
Compile in platform device definitions for FIMC controller 2
config S5P_DEV_FIMC3
bool
help
Compile in platform device definitions for FIMC controller 3
config S5P_DEV_FIMD0
bool
help
Compile in platform device definitions for FIMD controller 0
config S5P_DEV_G2D
bool
help
Compile in platform device definitions for G2D device
config S5P_DEV_I2C_HDMIPHY
bool
help
Compile in platform device definitions for I2C HDMIPHY controller
config S5P_DEV_JPEG
bool
help
Compile in platform device definitions for JPEG codec
config S5P_DEV_MFC
bool
help
Compile in setup memory (init) code for MFC
config S5P_DEV_ONENAND
bool
help
Compile in platform device definition for OneNAND controller
config S5P_DEV_TV
bool
help
Compile in platform device definition for TV interface
config S5P_DEV_USB_EHCI
bool
help
Compile in platform device definition for USB EHCI
config S3C24XX_PWM
bool "PWM device support"
select PWM
select PWM_SAMSUNG
help
Support for exporting the PWM timer blocks via the pwm device
system
config S5P_SETUP_MIPIPHY
bool
help
Compile in common setup code for MIPI-CSIS and MIPI-DSIM devices
config S3C_SETUP_CAMIF
bool
help
Compile in common setup code for S3C CAMIF devices
# DMA
config S3C_DMA
bool
help
Internal configuration for S3C DMA core
config SAMSUNG_DMADEV
bool
select ARM_AMBA
select DMADEVICES
select PL330_DMA if (ARCH_EXYNOS5 || ARCH_EXYNOS4 || CPU_S5PV210 || CPU_S5PC100 || \
CPU_S5P6450 || CPU_S5P6440)
help
Use DMA device engine for PL330 DMAC.
comment "Power management"
config SAMSUNG_PM_DEBUG
bool "S3C2410 PM Suspend debug"
depends on PM
select DEBUG_LL
help
Say Y here if you want verbose debugging from the PM Suspend and
Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
for more information.
config S3C_PM_DEBUG_LED_SMDK
bool "SMDK LED suspend/resume debugging"
depends on PM && (MACH_SMDK6410)
help
Say Y here to enable the use of the SMDK LEDs on the baseboard
for debugging of the state of the suspend and resume process.
Note, this currently only works for S3C64XX based SMDK boards.
config SAMSUNG_PM_CHECK
bool "S3C2410 PM Suspend Memory CRC"
depends on PM && CRC32
help
Enable the PM code's memory area checksum over sleep. This option
will generate CRCs of all blocks of memory, and store them before
going to sleep. The blocks are then checked on resume for any
errors.
Note, this can take several seconds depending on memory size
and CPU speed.
See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
config SAMSUNG_PM_CHECK_CHUNKSIZE
int "S3C2410 PM Suspend CRC Chunksize (KiB)"
depends on PM && SAMSUNG_PM_CHECK
default 64
help
Set the chunksize in Kilobytes of the CRC for checking memory
corruption over suspend and resume. A smaller value will mean that
the CRC data block will take more memory, but wil identify any
faults with better precision.
See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
config SAMSUNG_WAKEMASK
bool
depends on PM
help
Compile support for wakeup-mask controls found on the S3C6400
and above. This code allows a set of interrupt to wakeup-mask
mappings. See <plat/wakeup-mask.h>
config S5P_PM
bool
help
Common code for power management support on S5P and newer SoCs
Note: Do not select this for S5P6440 and S5P6450.
config S5P_SLEEP
bool
help
Internal config node to apply common S5P sleep management code.
Can be selected by S5P and newer SoCs with similar sleep procedure.
config DEBUG_S3C_UART
depends on PLAT_SAMSUNG
int
default "0" if DEBUG_S3C_UART0
default "1" if DEBUG_S3C_UART1
default "2" if DEBUG_S3C_UART2
default "3" if DEBUG_S3C_UART3
endif

View File

@@ -0,0 +1,61 @@
# arch/arm/plat-samsung/Makefile
#
# Copyright 2009 Simtec Electronics
#
# Licensed under GPLv2
obj-y :=
obj-m :=
obj-n := dummy.o
obj- :=
# Objects we always build independent of SoC choice
obj-y += init.o cpu.o
obj-$(CONFIG_SAMSUNG_HRT) += samsung-time.o
obj-$(CONFIG_SAMSUNG_CLOCK) += clock.o
obj-$(CONFIG_SAMSUNG_CLOCK) += pwm-clock.o
obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
obj-$(CONFIG_S5P_CLOCK) += s5p-clock.o
obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o
obj-$(CONFIG_S5P_IRQ) += s5p-irq.o
obj-$(CONFIG_S5P_EXT_INT) += s5p-irq-eint.o
obj-$(CONFIG_S5P_GPIO_INT) += s5p-irq-gpioint.o
# ADC
obj-$(CONFIG_S3C_ADC) += adc.o
# devices
obj-y += platformdata.o
obj-y += devs.o
obj-y += dev-uart.o
obj-$(CONFIG_S5P_DEV_MFC) += s5p-dev-mfc.o
obj-$(CONFIG_S5P_DEV_UART) += s5p-dev-uart.o
obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT) += dev-backlight.o
obj-$(CONFIG_S3C_SETUP_CAMIF) += setup-camif.o
obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o
# DMA support
obj-$(CONFIG_S3C_DMA) += dma.o s3c-dma-ops.o
obj-$(CONFIG_SAMSUNG_DMADEV) += dma-ops.o
# PM support
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_PM) += pm-gpio.o
obj-$(CONFIG_SAMSUNG_PM_CHECK) += pm-check.o
obj-$(CONFIG_SAMSUNG_WAKEMASK) += wakeup-mask.o
obj-$(CONFIG_S5P_PM) += s5p-pm.o s5p-irq-pm.o
obj-$(CONFIG_S5P_SLEEP) += s5p-sleep.o

526
arch/arm/plat-samsung/adc.c Normal file
View File

@@ -0,0 +1,526 @@
/* arch/arm/plat-samsung/adc.c
*
* Copyright (c) 2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
*
* Samsung ADC device core
*
* 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.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/regulator/consumer.h>
#include <plat/regs-adc.h>
#include <plat/adc.h>
/* This driver is designed to control the usage of the ADC block between
* the touchscreen and any other drivers that may need to use it, such as
* the hwmon driver.
*
* Priority will be given to the touchscreen driver, but as this itself is
* rate limited it should not starve other requests which are processed in
* order that they are received.
*
* Each user registers to get a client block which uniquely identifies it
* and stores information such as the necessary functions to callback when
* action is required.
*/
enum s3c_cpu_type {
TYPE_ADCV1, /* S3C24XX */
TYPE_ADCV11, /* S3C2443 */
TYPE_ADCV12, /* S3C2416, S3C2450 */
TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
};
struct s3c_adc_client {
struct platform_device *pdev;
struct list_head pend;
wait_queue_head_t *wait;
unsigned int nr_samples;
int result;
unsigned char is_ts;
unsigned char channel;
void (*select_cb)(struct s3c_adc_client *c, unsigned selected);
void (*convert_cb)(struct s3c_adc_client *c,
unsigned val1, unsigned val2,
unsigned *samples_left);
};
struct adc_device {
struct platform_device *pdev;
struct platform_device *owner;
struct clk *clk;
struct s3c_adc_client *cur;
struct s3c_adc_client *ts_pend;
void __iomem *regs;
spinlock_t lock;
unsigned int prescale;
int irq;
struct regulator *vdd;
};
static struct adc_device *adc_dev;
static LIST_HEAD(adc_pending); /* protected by adc_device.lock */
#define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg)
static inline void s3c_adc_convert(struct adc_device *adc)
{
unsigned con = readl(adc->regs + S3C2410_ADCCON);
con |= S3C2410_ADCCON_ENABLE_START;
writel(con, adc->regs + S3C2410_ADCCON);
}
static inline void s3c_adc_select(struct adc_device *adc,
struct s3c_adc_client *client)
{
unsigned con = readl(adc->regs + S3C2410_ADCCON);
enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
client->select_cb(client, 1);
if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV2)
con &= ~S3C2410_ADCCON_MUXMASK;
con &= ~S3C2410_ADCCON_STDBM;
con &= ~S3C2410_ADCCON_STARTMASK;
if (!client->is_ts) {
if (cpu == TYPE_ADCV3)
writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
else if (cpu == TYPE_ADCV11 || cpu == TYPE_ADCV12)
writel(client->channel & 0xf,
adc->regs + S3C2443_ADCMUX);
else
con |= S3C2410_ADCCON_SELMUX(client->channel);
}
writel(con, adc->regs + S3C2410_ADCCON);
}
static void s3c_adc_dbgshow(struct adc_device *adc)
{
adc_dbg(adc, "CON=%08x, TSC=%08x, DLY=%08x\n",
readl(adc->regs + S3C2410_ADCCON),
readl(adc->regs + S3C2410_ADCTSC),
readl(adc->regs + S3C2410_ADCDLY));
}
static void s3c_adc_try(struct adc_device *adc)
{
struct s3c_adc_client *next = adc->ts_pend;
if (!next && !list_empty(&adc_pending)) {
next = list_first_entry(&adc_pending,
struct s3c_adc_client, pend);
list_del(&next->pend);
} else
adc->ts_pend = NULL;
if (next) {
adc_dbg(adc, "new client is %p\n", next);
adc->cur = next;
s3c_adc_select(adc, next);
s3c_adc_convert(adc);
s3c_adc_dbgshow(adc);
}
}
int s3c_adc_start(struct s3c_adc_client *client,
unsigned int channel, unsigned int nr_samples)
{
struct adc_device *adc = adc_dev;
unsigned long flags;
if (!adc) {
printk(KERN_ERR "%s: failed to find adc\n", __func__);
return -EINVAL;
}
spin_lock_irqsave(&adc->lock, flags);
if (client->is_ts && adc->ts_pend) {
spin_unlock_irqrestore(&adc->lock, flags);
return -EAGAIN;
}
client->channel = channel;
client->nr_samples = nr_samples;
if (client->is_ts)
adc->ts_pend = client;
else
list_add_tail(&client->pend, &adc_pending);
if (!adc->cur)
s3c_adc_try(adc);
spin_unlock_irqrestore(&adc->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(s3c_adc_start);
static void s3c_convert_done(struct s3c_adc_client *client,
unsigned v, unsigned u, unsigned *left)
{
client->result = v;
wake_up(client->wait);
}
int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch)
{
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
int ret;
client->convert_cb = s3c_convert_done;
client->wait = &wake;
client->result = -1;
ret = s3c_adc_start(client, ch, 1);
if (ret < 0)
goto err;
ret = wait_event_timeout(wake, client->result >= 0, HZ / 2);
if (client->result < 0) {
ret = -ETIMEDOUT;
goto err;
}
client->convert_cb = NULL;
return client->result;
err:
return ret;
}
EXPORT_SYMBOL_GPL(s3c_adc_read);
static void s3c_adc_default_select(struct s3c_adc_client *client,
unsigned select)
{
}
struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
void (*select)(struct s3c_adc_client *client,
unsigned int selected),
void (*conv)(struct s3c_adc_client *client,
unsigned d0, unsigned d1,
unsigned *samples_left),
unsigned int is_ts)
{
struct s3c_adc_client *client;
WARN_ON(!pdev);
if (!select)
select = s3c_adc_default_select;
if (!pdev)
return ERR_PTR(-EINVAL);
client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL);
if (!client) {
dev_err(&pdev->dev, "no memory for adc client\n");
return ERR_PTR(-ENOMEM);
}
client->pdev = pdev;
client->is_ts = is_ts;
client->select_cb = select;
client->convert_cb = conv;
return client;
}
EXPORT_SYMBOL_GPL(s3c_adc_register);
void s3c_adc_release(struct s3c_adc_client *client)
{
unsigned long flags;
spin_lock_irqsave(&adc_dev->lock, flags);
/* We should really check that nothing is in progress. */
if (adc_dev->cur == client)
adc_dev->cur = NULL;
if (adc_dev->ts_pend == client)
adc_dev->ts_pend = NULL;
else {
struct list_head *p, *n;
struct s3c_adc_client *tmp;
list_for_each_safe(p, n, &adc_pending) {
tmp = list_entry(p, struct s3c_adc_client, pend);
if (tmp == client)
list_del(&tmp->pend);
}
}
if (adc_dev->cur == NULL)
s3c_adc_try(adc_dev);
spin_unlock_irqrestore(&adc_dev->lock, flags);
kfree(client);
}
EXPORT_SYMBOL_GPL(s3c_adc_release);
static irqreturn_t s3c_adc_irq(int irq, void *pw)
{
struct adc_device *adc = pw;
struct s3c_adc_client *client = adc->cur;
enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
unsigned data0, data1;
if (!client) {
dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__);
goto exit;
}
data0 = readl(adc->regs + S3C2410_ADCDAT0);
data1 = readl(adc->regs + S3C2410_ADCDAT1);
adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1);
client->nr_samples--;
if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV11) {
data0 &= 0x3ff;
data1 &= 0x3ff;
} else {
/* S3C2416/S3C64XX/S5P ADC resolution is 12-bit */
data0 &= 0xfff;
data1 &= 0xfff;
}
if (client->convert_cb)
(client->convert_cb)(client, data0, data1, &client->nr_samples);
if (client->nr_samples > 0) {
/* fire another conversion for this */
client->select_cb(client, 1);
s3c_adc_convert(adc);
} else {
spin_lock(&adc->lock);
(client->select_cb)(client, 0);
adc->cur = NULL;
s3c_adc_try(adc);
spin_unlock(&adc->lock);
}
exit:
if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3) {
/* Clear ADC interrupt */
writel(0, adc->regs + S3C64XX_ADCCLRINT);
}
return IRQ_HANDLED;
}
static int s3c_adc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct adc_device *adc;
struct resource *regs;
enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
int ret;
unsigned tmp;
adc = devm_kzalloc(dev, sizeof(struct adc_device), GFP_KERNEL);
if (adc == NULL) {
dev_err(dev, "failed to allocate adc_device\n");
return -ENOMEM;
}
spin_lock_init(&adc->lock);
adc->pdev = pdev;
adc->prescale = S3C2410_ADCCON_PRSCVL(49);
adc->vdd = devm_regulator_get(dev, "vdd");
if (IS_ERR(adc->vdd)) {
dev_err(dev, "operating without regulator \"vdd\" .\n");
return PTR_ERR(adc->vdd);
}
adc->irq = platform_get_irq(pdev, 1);
if (adc->irq <= 0) {
dev_err(dev, "failed to get adc irq\n");
return -ENOENT;
}
ret = devm_request_irq(dev, adc->irq, s3c_adc_irq, 0, dev_name(dev),
adc);
if (ret < 0) {
dev_err(dev, "failed to attach adc irq\n");
return ret;
}
adc->clk = devm_clk_get(dev, "adc");
if (IS_ERR(adc->clk)) {
dev_err(dev, "failed to get adc clock\n");
return PTR_ERR(adc->clk);
}
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
adc->regs = devm_ioremap_resource(dev, regs);
if (IS_ERR(adc->regs))
return PTR_ERR(adc->regs);
ret = regulator_enable(adc->vdd);
if (ret)
return ret;
clk_enable(adc->clk);
tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
/* Enable 12-bit ADC resolution */
if (cpu == TYPE_ADCV12)
tmp |= S3C2416_ADCCON_RESSEL;
if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
tmp |= S3C64XX_ADCCON_RESSEL;
writel(tmp, adc->regs + S3C2410_ADCCON);
dev_info(dev, "attached adc driver\n");
platform_set_drvdata(pdev, adc);
adc_dev = adc;
return 0;
}
static int s3c_adc_remove(struct platform_device *pdev)
{
struct adc_device *adc = platform_get_drvdata(pdev);
clk_disable(adc->clk);
regulator_disable(adc->vdd);
return 0;
}
#ifdef CONFIG_PM
static int s3c_adc_suspend(struct device *dev)
{
struct platform_device *pdev = container_of(dev,
struct platform_device, dev);
struct adc_device *adc = platform_get_drvdata(pdev);
unsigned long flags;
u32 con;
spin_lock_irqsave(&adc->lock, flags);
con = readl(adc->regs + S3C2410_ADCCON);
con |= S3C2410_ADCCON_STDBM;
writel(con, adc->regs + S3C2410_ADCCON);
disable_irq(adc->irq);
spin_unlock_irqrestore(&adc->lock, flags);
clk_disable(adc->clk);
regulator_disable(adc->vdd);
return 0;
}
static int s3c_adc_resume(struct device *dev)
{
struct platform_device *pdev = container_of(dev,
struct platform_device, dev);
struct adc_device *adc = platform_get_drvdata(pdev);
enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
int ret;
unsigned long tmp;
ret = regulator_enable(adc->vdd);
if (ret)
return ret;
clk_enable(adc->clk);
enable_irq(adc->irq);
tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
/* Enable 12-bit ADC resolution */
if (cpu == TYPE_ADCV12)
tmp |= S3C2416_ADCCON_RESSEL;
if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
tmp |= S3C64XX_ADCCON_RESSEL;
writel(tmp, adc->regs + S3C2410_ADCCON);
return 0;
}
#else
#define s3c_adc_suspend NULL
#define s3c_adc_resume NULL
#endif
static struct platform_device_id s3c_adc_driver_ids[] = {
{
.name = "s3c24xx-adc",
.driver_data = TYPE_ADCV1,
}, {
.name = "s3c2443-adc",
.driver_data = TYPE_ADCV11,
}, {
.name = "s3c2416-adc",
.driver_data = TYPE_ADCV12,
}, {
.name = "s3c64xx-adc",
.driver_data = TYPE_ADCV2,
}, {
.name = "samsung-adc-v3",
.driver_data = TYPE_ADCV3,
},
{ }
};
MODULE_DEVICE_TABLE(platform, s3c_adc_driver_ids);
static const struct dev_pm_ops adc_pm_ops = {
.suspend = s3c_adc_suspend,
.resume = s3c_adc_resume,
};
static struct platform_driver s3c_adc_driver = {
.id_table = s3c_adc_driver_ids,
.driver = {
.name = "s3c-adc",
.owner = THIS_MODULE,
.pm = &adc_pm_ops,
},
.probe = s3c_adc_probe,
.remove = s3c_adc_remove,
};
static int __init adc_init(void)
{
int ret;
ret = platform_driver_register(&s3c_adc_driver);
if (ret)
printk(KERN_ERR "%s: failed to add adc driver\n", __func__);
return ret;
}
module_init(adc_init);

View File

@@ -0,0 +1,212 @@
/* linux/arch/arm/plat-samsung/clock-clksrc.c
*
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* 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/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
#include <plat/clock.h>
#include <plat/clock-clksrc.h>
#include <plat/cpu-freq.h>
static inline struct clksrc_clk *to_clksrc(struct clk *clk)
{
return container_of(clk, struct clksrc_clk, clk);
}
static inline u32 bit_mask(u32 shift, u32 nr_bits)
{
u32 mask = 0xffffffff >> (32 - nr_bits);
return mask << shift;
}
static unsigned long s3c_getrate_clksrc(struct clk *clk)
{
struct clksrc_clk *sclk = to_clksrc(clk);
unsigned long rate = clk_get_rate(clk->parent);
u32 clkdiv = __raw_readl(sclk->reg_div.reg);
u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size);
clkdiv &= mask;
clkdiv >>= sclk->reg_div.shift;
clkdiv++;
rate /= clkdiv;
return rate;
}
static int s3c_setrate_clksrc(struct clk *clk, unsigned long rate)
{
struct clksrc_clk *sclk = to_clksrc(clk);
void __iomem *reg = sclk->reg_div.reg;
unsigned int div;
u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size);
u32 val;
rate = clk_round_rate(clk, rate);
div = clk_get_rate(clk->parent) / rate;
if (div > (1 << sclk->reg_div.size))
return -EINVAL;
val = __raw_readl(reg);
val &= ~mask;
val |= (div - 1) << sclk->reg_div.shift;
__raw_writel(val, reg);
return 0;
}
static int s3c_setparent_clksrc(struct clk *clk, struct clk *parent)
{
struct clksrc_clk *sclk = to_clksrc(clk);
struct clksrc_sources *srcs = sclk->sources;
u32 clksrc = __raw_readl(sclk->reg_src.reg);
u32 mask = bit_mask(sclk->reg_src.shift, sclk->reg_src.size);
int src_nr = -1;
int ptr;
for (ptr = 0; ptr < srcs->nr_sources; ptr++)
if (srcs->sources[ptr] == parent) {
src_nr = ptr;
break;
}
if (src_nr >= 0) {
clk->parent = parent;
clksrc &= ~mask;
clksrc |= src_nr << sclk->reg_src.shift;
__raw_writel(clksrc, sclk->reg_src.reg);
return 0;
}
return -EINVAL;
}
static unsigned long s3c_roundrate_clksrc(struct clk *clk,
unsigned long rate)
{
struct clksrc_clk *sclk = to_clksrc(clk);
unsigned long parent_rate = clk_get_rate(clk->parent);
int max_div = 1 << sclk->reg_div.size;
int div;
if (rate >= parent_rate)
rate = parent_rate;
else {
div = parent_rate / rate;
if (parent_rate % rate)
div++;
if (div == 0)
div = 1;
if (div > max_div)
div = max_div;
rate = parent_rate / div;
}
return rate;
}
/* Clock initialisation code */
void __init_or_cpufreq s3c_set_clksrc(struct clksrc_clk *clk, bool announce)
{
struct clksrc_sources *srcs = clk->sources;
u32 mask = bit_mask(clk->reg_src.shift, clk->reg_src.size);
u32 clksrc;
if (!clk->reg_src.reg) {
if (!clk->clk.parent)
printk(KERN_ERR "%s: no parent clock specified\n",
clk->clk.name);
return;
}
clksrc = __raw_readl(clk->reg_src.reg);
clksrc &= mask;
clksrc >>= clk->reg_src.shift;
if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
printk(KERN_ERR "%s: bad source %d\n",
clk->clk.name, clksrc);
return;
}
clk->clk.parent = srcs->sources[clksrc];
if (announce)
printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n",
clk->clk.name, clk->clk.parent->name, clksrc,
clk_get_rate(&clk->clk));
}
static struct clk_ops clksrc_ops = {
.set_parent = s3c_setparent_clksrc,
.get_rate = s3c_getrate_clksrc,
.set_rate = s3c_setrate_clksrc,
.round_rate = s3c_roundrate_clksrc,
};
static struct clk_ops clksrc_ops_nodiv = {
.set_parent = s3c_setparent_clksrc,
};
static struct clk_ops clksrc_ops_nosrc = {
.get_rate = s3c_getrate_clksrc,
.set_rate = s3c_setrate_clksrc,
.round_rate = s3c_roundrate_clksrc,
};
void __init s3c_register_clksrc(struct clksrc_clk *clksrc, int size)
{
int ret;
for (; size > 0; size--, clksrc++) {
if (!clksrc->reg_div.reg && !clksrc->reg_src.reg)
printk(KERN_ERR "%s: clock %s has no registers set\n",
__func__, clksrc->clk.name);
/* fill in the default functions */
if (!clksrc->clk.ops) {
if (!clksrc->reg_div.reg)
clksrc->clk.ops = &clksrc_ops_nodiv;
else if (!clksrc->reg_src.reg)
clksrc->clk.ops = &clksrc_ops_nosrc;
else
clksrc->clk.ops = &clksrc_ops;
}
/* setup the clocksource, but do not announce it
* as it may be re-set by the setup routines
* called after the rest of the clocks have been
* registered
*/
s3c_set_clksrc(clksrc, false);
ret = s3c24xx_register_clock(&clksrc->clk);
if (ret < 0) {
printk(KERN_ERR "%s: failed to register %s (%d)\n",
__func__, clksrc->clk.name, ret);
}
}
}

View File

@@ -0,0 +1,540 @@
/* linux/arch/arm/plat-s3c24xx/clock.c
*
* Copyright 2004-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C24XX Core clock control support
*
* Based on, and code from linux/arch/arm/mach-versatile/clock.c
**
** Copyright (C) 2004 ARM Limited.
** Written by Deep Blue Solutions 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
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/clk.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#if defined(CONFIG_DEBUG_FS)
#include <linux/debugfs.h>
#endif
#include <mach/hardware.h>
#include <asm/irq.h>
#include <plat/cpu-freq.h>
#include <plat/clock.h>
#include <plat/cpu.h>
#include <linux/serial_core.h>
#include <plat/regs-serial.h> /* for s3c24xx_uart_devs */
/* clock information */
static LIST_HEAD(clocks);
/* We originally used an mutex here, but some contexts (see resume)
* are calling functions such as clk_set_parent() with IRQs disabled
* causing an BUG to be triggered.
*/
DEFINE_SPINLOCK(clocks_lock);
/* Global watchdog clock used by arch_wtd_reset() callback */
struct clk *s3c2410_wdtclk;
static int __init s3c_wdt_reset_init(void)
{
s3c2410_wdtclk = clk_get(NULL, "watchdog");
if (IS_ERR(s3c2410_wdtclk))
printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
return 0;
}
arch_initcall(s3c_wdt_reset_init);
/* enable and disable calls for use with the clk struct */
static int clk_null_enable(struct clk *clk, int enable)
{
return 0;
}
int clk_enable(struct clk *clk)
{
unsigned long flags;
if (IS_ERR(clk) || clk == NULL)
return -EINVAL;
clk_enable(clk->parent);
spin_lock_irqsave(&clocks_lock, flags);
if ((clk->usage++) == 0)
(clk->enable)(clk, 1);
spin_unlock_irqrestore(&clocks_lock, flags);
return 0;
}
void clk_disable(struct clk *clk)
{
unsigned long flags;
if (IS_ERR(clk) || clk == NULL)
return;
spin_lock_irqsave(&clocks_lock, flags);
if ((--clk->usage) == 0)
(clk->enable)(clk, 0);
spin_unlock_irqrestore(&clocks_lock, flags);
clk_disable(clk->parent);
}
unsigned long clk_get_rate(struct clk *clk)
{
if (IS_ERR_OR_NULL(clk))
return 0;
if (clk->rate != 0)
return clk->rate;
if (clk->ops != NULL && clk->ops->get_rate != NULL)
return (clk->ops->get_rate)(clk);
if (clk->parent != NULL)
return clk_get_rate(clk->parent);
return clk->rate;
}
long clk_round_rate(struct clk *clk, unsigned long rate)
{
if (!IS_ERR_OR_NULL(clk) && clk->ops && clk->ops->round_rate)
return (clk->ops->round_rate)(clk, rate);
return rate;
}
int clk_set_rate(struct clk *clk, unsigned long rate)
{
unsigned long flags;
int ret;
if (IS_ERR_OR_NULL(clk))
return -EINVAL;
/* We do not default just do a clk->rate = rate as
* the clock may have been made this way by choice.
*/
WARN_ON(clk->ops == NULL);
WARN_ON(clk->ops && clk->ops->set_rate == NULL);
if (clk->ops == NULL || clk->ops->set_rate == NULL)
return -EINVAL;
spin_lock_irqsave(&clocks_lock, flags);
ret = (clk->ops->set_rate)(clk, rate);
spin_unlock_irqrestore(&clocks_lock, flags);
return ret;
}
struct clk *clk_get_parent(struct clk *clk)
{
return clk->parent;
}
int clk_set_parent(struct clk *clk, struct clk *parent)
{
unsigned long flags;
int ret = 0;
if (IS_ERR_OR_NULL(clk) || IS_ERR_OR_NULL(parent))
return -EINVAL;
spin_lock_irqsave(&clocks_lock, flags);
if (clk->ops && clk->ops->set_parent)
ret = (clk->ops->set_parent)(clk, parent);
spin_unlock_irqrestore(&clocks_lock, flags);
return ret;
}
EXPORT_SYMBOL(clk_enable);
EXPORT_SYMBOL(clk_disable);
EXPORT_SYMBOL(clk_get_rate);
EXPORT_SYMBOL(clk_round_rate);
EXPORT_SYMBOL(clk_set_rate);
EXPORT_SYMBOL(clk_get_parent);
EXPORT_SYMBOL(clk_set_parent);
/* base clocks */
int clk_default_setrate(struct clk *clk, unsigned long rate)
{
clk->rate = rate;
return 0;
}
struct clk_ops clk_ops_def_setrate = {
.set_rate = clk_default_setrate,
};
struct clk clk_xtal = {
.name = "xtal",
.rate = 0,
.parent = NULL,
.ctrlbit = 0,
};
struct clk clk_ext = {
.name = "ext",
};
struct clk clk_epll = {
.name = "epll",
};
struct clk clk_mpll = {
.name = "mpll",
.ops = &clk_ops_def_setrate,
};
struct clk clk_upll = {
.name = "upll",
.parent = NULL,
.ctrlbit = 0,
};
struct clk clk_f = {
.name = "fclk",
.rate = 0,
.parent = &clk_mpll,
.ctrlbit = 0,
};
struct clk clk_h = {
.name = "hclk",
.rate = 0,
.parent = NULL,
.ctrlbit = 0,
.ops = &clk_ops_def_setrate,
};
struct clk clk_p = {
.name = "pclk",
.rate = 0,
.parent = NULL,
.ctrlbit = 0,
.ops = &clk_ops_def_setrate,
};
struct clk clk_usb_bus = {
.name = "usb-bus",
.rate = 0,
.parent = &clk_upll,
};
struct clk s3c24xx_uclk = {
.name = "uclk",
};
/* initialise the clock system */
/**
* s3c24xx_register_clock() - register a clock
* @clk: The clock to register
*
* Add the specified clock to the list of clocks known by the system.
*/
int s3c24xx_register_clock(struct clk *clk)
{
if (clk->enable == NULL)
clk->enable = clk_null_enable;
/* fill up the clk_lookup structure and register it*/
clk->lookup.dev_id = clk->devname;
clk->lookup.con_id = clk->name;
clk->lookup.clk = clk;
clkdev_add(&clk->lookup);
return 0;
}
/**
* s3c24xx_register_clocks() - register an array of clock pointers
* @clks: Pointer to an array of struct clk pointers
* @nr_clks: The number of clocks in the @clks array.
*
* Call s3c24xx_register_clock() for all the clock pointers contained
* in the @clks list. Returns the number of failures.
*/
int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
{
int fails = 0;
for (; nr_clks > 0; nr_clks--, clks++) {
if (s3c24xx_register_clock(*clks) < 0) {
struct clk *clk = *clks;
printk(KERN_ERR "%s: failed to register %p: %s\n",
__func__, clk, clk->name);
fails++;
}
}
return fails;
}
/**
* s3c_register_clocks() - register an array of clocks
* @clkp: Pointer to the first clock in the array.
* @nr_clks: Number of clocks to register.
*
* Call s3c24xx_register_clock() on the @clkp array given, printing an
* error if it fails to register the clock (unlikely).
*/
void __init s3c_register_clocks(struct clk *clkp, int nr_clks)
{
int ret;
for (; nr_clks > 0; nr_clks--, clkp++) {
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
}
}
/**
* s3c_disable_clocks() - disable an array of clocks
* @clkp: Pointer to the first clock in the array.
* @nr_clks: Number of clocks to register.
*
* for internal use only at initialisation time. disable the clocks in the
* @clkp array.
*/
void __init s3c_disable_clocks(struct clk *clkp, int nr_clks)
{
for (; nr_clks > 0; nr_clks--, clkp++)
(clkp->enable)(clkp, 0);
}
/* initialise all the clocks */
int __init s3c24xx_register_baseclocks(unsigned long xtal)
{
printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n");
clk_xtal.rate = xtal;
/* register our clocks */
if (s3c24xx_register_clock(&clk_xtal) < 0)
printk(KERN_ERR "failed to register master xtal\n");
if (s3c24xx_register_clock(&clk_mpll) < 0)
printk(KERN_ERR "failed to register mpll clock\n");
if (s3c24xx_register_clock(&clk_upll) < 0)
printk(KERN_ERR "failed to register upll clock\n");
if (s3c24xx_register_clock(&clk_f) < 0)
printk(KERN_ERR "failed to register cpu fclk\n");
if (s3c24xx_register_clock(&clk_h) < 0)
printk(KERN_ERR "failed to register cpu hclk\n");
if (s3c24xx_register_clock(&clk_p) < 0)
printk(KERN_ERR "failed to register cpu pclk\n");
return 0;
}
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
/* debugfs support to trace clock tree hierarchy and attributes */
static struct dentry *clk_debugfs_root;
static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
{
struct clk *child;
const char *state;
char buf[255] = { 0 };
int n = 0;
if (c->name)
n = snprintf(buf, sizeof(buf) - 1, "%s", c->name);
if (c->devname)
n += snprintf(buf + n, sizeof(buf) - 1 - n, ":%s", c->devname);
state = (c->usage > 0) ? "on" : "off";
seq_printf(s, "%*s%-*s %-6s %-3d %-10lu\n",
level * 3 + 1, "",
50 - level * 3, buf,
state, c->usage, clk_get_rate(c));
list_for_each_entry(child, &clocks, list) {
if (child->parent != c)
continue;
clock_tree_show_one(s, child, level + 1);
}
}
static int clock_tree_show(struct seq_file *s, void *data)
{
struct clk *c;
unsigned long flags;
seq_printf(s, " clock state ref rate\n");
seq_printf(s, "----------------------------------------------------\n");
spin_lock_irqsave(&clocks_lock, flags);
list_for_each_entry(c, &clocks, list)
if (c->parent == NULL)
clock_tree_show_one(s, c, 0);
spin_unlock_irqrestore(&clocks_lock, flags);
return 0;
}
static int clock_tree_open(struct inode *inode, struct file *file)
{
return single_open(file, clock_tree_show, inode->i_private);
}
static const struct file_operations clock_tree_fops = {
.open = clock_tree_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int clock_rate_show(void *data, u64 *val)
{
struct clk *c = data;
*val = clk_get_rate(c);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_rate_show, NULL, "%llu\n");
static int clk_debugfs_register_one(struct clk *c)
{
int err;
struct dentry *d;
struct clk *pa = c->parent;
char s[255];
char *p = s;
p += sprintf(p, "%s", c->devname);
d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
if (!d)
return -ENOMEM;
c->dent = d;
d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usage);
if (!d) {
err = -ENOMEM;
goto err_out;
}
d = debugfs_create_file("rate", S_IRUGO, c->dent, c, &clock_rate_fops);
if (!d) {
err = -ENOMEM;
goto err_out;
}
return 0;
err_out:
debugfs_remove_recursive(c->dent);
return err;
}
static int clk_debugfs_register(struct clk *c)
{
int err;
struct clk *pa = c->parent;
if (pa && !pa->dent) {
err = clk_debugfs_register(pa);
if (err)
return err;
}
if (!c->dent) {
err = clk_debugfs_register_one(c);
if (err)
return err;
}
return 0;
}
static int __init clk_debugfs_init(void)
{
struct clk *c;
struct dentry *d;
int err = -ENOMEM;
d = debugfs_create_dir("clock", NULL);
if (!d)
return -ENOMEM;
clk_debugfs_root = d;
d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
&clock_tree_fops);
if (!d)
goto err_out;
list_for_each_entry(c, &clocks, list) {
err = clk_debugfs_register(c);
if (err)
goto err_out;
}
return 0;
err_out:
debugfs_remove_recursive(clk_debugfs_root);
return err;
}
late_initcall(clk_debugfs_init);
#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */

View File

@@ -0,0 +1,57 @@
/* linux/arch/arm/plat-samsung/cpu.c
*
* Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung CPU Support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <mach/map.h>
#include <plat/cpu.h>
unsigned long samsung_cpu_id;
static unsigned int samsung_cpu_rev;
unsigned int samsung_rev(void)
{
return samsung_cpu_rev;
}
EXPORT_SYMBOL(samsung_rev);
void __init s3c24xx_init_cpu(void)
{
/* nothing here yet */
samsung_cpu_rev = 0;
}
void __init s3c64xx_init_cpu(void)
{
samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118);
if (!samsung_cpu_id) {
/*
* S3C6400 has the ID register in a different place,
* and needs a write before it can be read.
*/
__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0xA1C);
}
samsung_cpu_rev = 0;
}
void __init s5p_init_cpu(void __iomem *cpuid_addr)
{
samsung_cpu_id = __raw_readl(cpuid_addr);
samsung_cpu_rev = samsung_cpu_id & 0xFF;
}

View File

@@ -0,0 +1,152 @@
/* linux/arch/arm/plat-samsung/dev-backlight.c
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Common infrastructure for PWM Backlight for Samsung boards
*
* 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/gpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/pwm_backlight.h>
#include <plat/devs.h>
#include <plat/gpio-cfg.h>
#include <plat/backlight.h>
static int samsung_bl_init(struct device *dev)
{
int ret = 0;
struct platform_device *timer_dev =
container_of(dev->parent, struct platform_device, dev);
struct samsung_bl_gpio_info *bl_gpio_info =
timer_dev->dev.platform_data;
ret = gpio_request(bl_gpio_info->no, "Backlight");
if (ret) {
printk(KERN_ERR "failed to request GPIO for LCD Backlight\n");
return ret;
}
/* Configure GPIO pin with specific GPIO function for PWM timer */
s3c_gpio_cfgpin(bl_gpio_info->no, bl_gpio_info->func);
return 0;
}
static void samsung_bl_exit(struct device *dev)
{
struct platform_device *timer_dev =
container_of(dev->parent, struct platform_device, dev);
struct samsung_bl_gpio_info *bl_gpio_info =
timer_dev->dev.platform_data;
s3c_gpio_cfgpin(bl_gpio_info->no, S3C_GPIO_OUTPUT);
gpio_free(bl_gpio_info->no);
}
/* Initialize few important fields of platform_pwm_backlight_data
* structure with default values. These fields can be overridden by
* board-specific values sent from machine file.
* For ease of operation, these fields are initialized with values
* used by most samsung boards.
* Users has the option of sending info about other parameters
* for their specific boards
*/
static struct platform_pwm_backlight_data samsung_dfl_bl_data __initdata = {
.max_brightness = 255,
.dft_brightness = 255,
.pwm_period_ns = 78770,
.init = samsung_bl_init,
.exit = samsung_bl_exit,
};
static struct platform_device samsung_dfl_bl_device __initdata = {
.name = "pwm-backlight",
};
/* samsung_bl_set - Set board specific data (if any) provided by user for
* PWM Backlight control and register specific PWM and backlight device.
* @gpio_info: structure containing GPIO info for PWM timer
* @bl_data: structure containing Backlight control data
*/
void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
struct platform_pwm_backlight_data *bl_data)
{
int ret = 0;
struct platform_device *samsung_bl_device;
struct platform_pwm_backlight_data *samsung_bl_data;
samsung_bl_device = kmemdup(&samsung_dfl_bl_device,
sizeof(struct platform_device), GFP_KERNEL);
if (!samsung_bl_device) {
printk(KERN_ERR "%s: no memory for platform dev\n", __func__);
return;
}
samsung_bl_data = s3c_set_platdata(&samsung_dfl_bl_data,
sizeof(struct platform_pwm_backlight_data), samsung_bl_device);
if (!samsung_bl_data) {
printk(KERN_ERR "%s: no memory for platform dev\n", __func__);
goto err_data;
}
/* Copy board specific data provided by user */
samsung_bl_data->pwm_id = bl_data->pwm_id;
samsung_bl_device->dev.parent =
&s3c_device_timer[samsung_bl_data->pwm_id].dev;
if (bl_data->max_brightness)
samsung_bl_data->max_brightness = bl_data->max_brightness;
if (bl_data->dft_brightness)
samsung_bl_data->dft_brightness = bl_data->dft_brightness;
if (bl_data->lth_brightness)
samsung_bl_data->lth_brightness = bl_data->lth_brightness;
if (bl_data->pwm_period_ns)
samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns;
if (bl_data->init)
samsung_bl_data->init = bl_data->init;
if (bl_data->notify)
samsung_bl_data->notify = bl_data->notify;
if (bl_data->notify_after)
samsung_bl_data->notify_after = bl_data->notify_after;
if (bl_data->exit)
samsung_bl_data->exit = bl_data->exit;
if (bl_data->check_fb)
samsung_bl_data->check_fb = bl_data->check_fb;
/* Keep the GPIO info for future use */
s3c_device_timer[samsung_bl_data->pwm_id].dev.platform_data = gpio_info;
/* Register the specific PWM timer dev for Backlight control */
ret = platform_device_register(
&s3c_device_timer[samsung_bl_data->pwm_id]);
if (ret) {
printk(KERN_ERR "failed to register pwm timer for backlight: %d\n", ret);
goto err_plat_reg1;
}
/* Register the Backlight dev */
ret = platform_device_register(samsung_bl_device);
if (ret) {
printk(KERN_ERR "failed to register backlight device: %d\n", ret);
goto err_plat_reg2;
}
return;
err_plat_reg2:
platform_device_unregister(&s3c_device_timer[samsung_bl_data->pwm_id]);
err_plat_reg1:
kfree(samsung_bl_data);
err_data:
kfree(samsung_bl_device);
return;
}

View File

@@ -0,0 +1,46 @@
/* linux/arch/arm/plat-samsung/dev-uart.c
* originally from arch/arm/plat-s3c24xx/devs.c
*x
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Base S3C24XX platform device definitions
*
* 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 <plat/devs.h>
/* uart devices */
static struct platform_device s3c24xx_uart_device0 = {
.id = 0,
};
static struct platform_device s3c24xx_uart_device1 = {
.id = 1,
};
static struct platform_device s3c24xx_uart_device2 = {
.id = 2,
};
static struct platform_device s3c24xx_uart_device3 = {
.id = 3,
};
struct platform_device *s3c24xx_uart_src[4] = {
&s3c24xx_uart_device0,
&s3c24xx_uart_device1,
&s3c24xx_uart_device2,
&s3c24xx_uart_device3,
};
struct platform_device *s3c24xx_uart_devs[4] = {
};

1604
arch/arm/plat-samsung/devs.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,140 @@
/* linux/arch/arm/plat-samsung/dma-ops.c
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung DMA Operations
*
* 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/errno.h>
#include <linux/amba/pl330.h>
#include <linux/scatterlist.h>
#include <linux/export.h>
#include <mach/dma.h>
static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
struct samsung_dma_req *param,
struct device *dev, char *ch_name)
{
dma_cap_mask_t mask;
dma_cap_zero(mask);
dma_cap_set(param->cap, mask);
if (dev->of_node)
return (unsigned)dma_request_slave_channel(dev, ch_name);
else
return (unsigned)dma_request_channel(mask, pl330_filter,
(void *)dma_ch);
}
static int samsung_dmadev_release(unsigned ch, void *param)
{
dma_release_channel((struct dma_chan *)ch);
return 0;
}
static int samsung_dmadev_config(unsigned ch,
struct samsung_dma_config *param)
{
struct dma_chan *chan = (struct dma_chan *)ch;
struct dma_slave_config slave_config;
if (param->direction == DMA_DEV_TO_MEM) {
memset(&slave_config, 0, sizeof(struct dma_slave_config));
slave_config.direction = param->direction;
slave_config.src_addr = param->fifo;
slave_config.src_addr_width = param->width;
slave_config.src_maxburst = 1;
dmaengine_slave_config(chan, &slave_config);
} else if (param->direction == DMA_MEM_TO_DEV) {
memset(&slave_config, 0, sizeof(struct dma_slave_config));
slave_config.direction = param->direction;
slave_config.dst_addr = param->fifo;
slave_config.dst_addr_width = param->width;
slave_config.dst_maxburst = 1;
dmaengine_slave_config(chan, &slave_config);
} else {
pr_warn("unsupported direction\n");
return -EINVAL;
}
return 0;
}
static int samsung_dmadev_prepare(unsigned ch,
struct samsung_dma_prep *param)
{
struct scatterlist sg;
struct dma_chan *chan = (struct dma_chan *)ch;
struct dma_async_tx_descriptor *desc;
switch (param->cap) {
case DMA_SLAVE:
sg_init_table(&sg, 1);
sg_dma_len(&sg) = param->len;
sg_set_page(&sg, pfn_to_page(PFN_DOWN(param->buf)),
param->len, offset_in_page(param->buf));
sg_dma_address(&sg) = param->buf;
desc = dmaengine_prep_slave_sg(chan,
&sg, 1, param->direction, DMA_PREP_INTERRUPT);
break;
case DMA_CYCLIC:
desc = dmaengine_prep_dma_cyclic(chan, param->buf,
param->len, param->period, param->direction,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
break;
default:
dev_err(&chan->dev->device, "unsupported format\n");
return -EFAULT;
}
if (!desc) {
dev_err(&chan->dev->device, "cannot prepare cyclic dma\n");
return -EFAULT;
}
desc->callback = param->fp;
desc->callback_param = param->fp_param;
dmaengine_submit((struct dma_async_tx_descriptor *)desc);
return 0;
}
static inline int samsung_dmadev_trigger(unsigned ch)
{
dma_async_issue_pending((struct dma_chan *)ch);
return 0;
}
static inline int samsung_dmadev_flush(unsigned ch)
{
return dmaengine_terminate_all((struct dma_chan *)ch);
}
static struct samsung_dma_ops dmadev_ops = {
.request = samsung_dmadev_request,
.release = samsung_dmadev_release,
.config = samsung_dmadev_config,
.prepare = samsung_dmadev_prepare,
.trigger = samsung_dmadev_trigger,
.started = NULL,
.flush = samsung_dmadev_flush,
.stop = samsung_dmadev_flush,
};
void *samsung_dmadev_get_ops(void)
{
return &dmadev_ops;
}
EXPORT_SYMBOL(samsung_dmadev_get_ops);

View File

@@ -0,0 +1,84 @@
/* linux/arch/arm/plat-samsung/dma.c
*
* Copyright (c) 2003-2009 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* S3C DMA core
*
* 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.
*/
struct s3c2410_dma_buf;
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <mach/dma.h>
#include <mach/irqs.h>
/* dma channel state information */
struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
struct s3c2410_dma_chan *s3c_dma_chan_map[DMACH_MAX];
/* s3c_dma_lookup_channel
*
* change the dma channel number given into a real dma channel id
*/
struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel)
{
if (channel & DMACH_LOW_LEVEL)
return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
else
return s3c_dma_chan_map[channel];
}
/* do we need to protect the settings of the fields from
* irq?
*/
int s3c2410_dma_set_opfn(enum dma_ch channel, s3c2410_dma_opfn_t rtn)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
if (chan == NULL)
return -EINVAL;
pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
chan->op_fn = rtn;
return 0;
}
EXPORT_SYMBOL(s3c2410_dma_set_opfn);
int s3c2410_dma_set_buffdone_fn(enum dma_ch channel, s3c2410_dma_cbfn_t rtn)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
if (chan == NULL)
return -EINVAL;
pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
chan->callback_fn = rtn;
return 0;
}
EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
int s3c2410_dma_setflags(enum dma_ch channel, unsigned int flags)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
if (chan == NULL)
return -EINVAL;
chan->flags = flags;
return 0;
}
EXPORT_SYMBOL(s3c2410_dma_setflags);

View File

@@ -0,0 +1,28 @@
/* linux/arch/arm/plat-samsung/include/plat/adc-core.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* Samsung ADC Controller core functions
*
* 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.
*/
#ifndef __ASM_PLAT_ADC_CORE_H
#define __ASM_PLAT_ADC_CORE_H __FILE__
/* These functions are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void s3c_adc_setname(char *name)
{
#if defined(CONFIG_SAMSUNG_DEV_ADC) || defined(CONFIG_PLAT_S3C24XX)
s3c_device_adc.name = name;
#endif
}
#endif /* __ASM_PLAT_ADC_CORE_H */

View File

@@ -0,0 +1,36 @@
/* arch/arm/plat-samsung/include/plat/adc.h
*
* Copyright (c) 2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C ADC driver information
*
* 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.
*/
#ifndef __ASM_PLAT_ADC_H
#define __ASM_PLAT_ADC_H __FILE__
struct s3c_adc_client;
struct platform_device;
extern int s3c_adc_start(struct s3c_adc_client *client,
unsigned int channel, unsigned int nr_samples);
extern int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch);
extern struct s3c_adc_client *
s3c_adc_register(struct platform_device *pdev,
void (*select)(struct s3c_adc_client *client,
unsigned selected),
void (*conv)(struct s3c_adc_client *client,
unsigned d0, unsigned d1,
unsigned *samples_left),
unsigned int is_ts);
extern void s3c_adc_release(struct s3c_adc_client *client);
#endif /* __ASM_PLAT_ADC_H */

View File

@@ -0,0 +1,28 @@
/* linux/arch/arm/plat-samsung/include/plat/ata-core.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung CF-ATA Controller core functions
*
* 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.
*/
#ifndef __ASM_PLAT_ATA_CORE_H
#define __ASM_PLAT_ATA_CORE_H __FILE__
/* These functions are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void s3c_cfcon_setname(char *name)
{
#ifdef CONFIG_SAMSUNG_DEV_IDE
s3c_device_cfcon.name = name;
#endif
}
#endif /* __ASM_PLAT_ATA_CORE_H */

View File

@@ -0,0 +1,26 @@
/* linux/arch/arm/plat-samsung/include/plat/backlight.h
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.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.
*/
#ifndef __ASM_PLAT_BACKLIGHT_H
#define __ASM_PLAT_BACKLIGHT_H __FILE__
/* samsung_bl_gpio_info - GPIO info for PWM Backlight control
* @no: GPIO number for PWM timer out
* @func: Special function of GPIO line for PWM timer
*/
struct samsung_bl_gpio_info {
int no;
int func;
};
extern void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
struct platform_pwm_backlight_data *bl_data);
#endif /* __ASM_PLAT_BACKLIGHT_H */

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
*
* S5P series camera interface helper functions
*
* 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.
*/
#ifndef __PLAT_SAMSUNG_CAMPORT_H_
#define __PLAT_SAMSUNG_CAMPORT_H_ __FILE__
enum s5p_camport_id {
S5P_CAMPORT_A,
S5P_CAMPORT_B,
};
/*
* The helper functions to configure GPIO for the camera parallel bus.
* The camera port can be multiplexed with any FIMC entity, even multiple
* FIMC entities are allowed to be attached to a single port simultaneously.
* These functions are to be used in the board setup code.
*/
int s5pv210_fimc_setup_gpio(enum s5p_camport_id id);
int exynos4_fimc_setup_gpio(enum s5p_camport_id id);
#endif /* __PLAT_SAMSUNG_CAMPORT_H */

View File

@@ -0,0 +1,83 @@
/* linux/arch/arm/plat-samsung/include/plat/clock-clksrc.h
*
* Parts taken from arch/arm/plat-s3c64xx/clock.c
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* Copyright 2009 Ben Dooks <ben-linux@fluff.org>
* Copyright 2009 Harald Welte
*
* 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.
*/
/**
* struct clksrc_sources - list of sources for a given clock
* @sources: array of pointers to clocks
* @nr_sources: The size of @sources
*/
struct clksrc_sources {
unsigned int nr_sources;
struct clk **sources;
};
/**
* struct clksrc_reg - register definition for clock control bits
* @reg: pointer to the register in virtual memory.
* @shift: the shift in bits to where the bitfield is.
* @size: the size in bits of the bitfield.
*
* This specifies the size and position of the bits we are interested
* in within the register specified by @reg.
*/
struct clksrc_reg {
void __iomem *reg;
unsigned short shift;
unsigned short size;
};
/**
* struct clksrc_clk - class of clock for newer style samsung devices.
* @clk: the standard clock representation
* @sources: the sources for this clock
* @reg_src: the register definition for selecting the clock's source
* @reg_div: the register definition for the clock's output divisor
*
* This clock implements the features required by the newer SoCs where
* the standard clock block provides an input mux and a post-mux divisor
* to provide the periperhal's clock.
*
* The array of @sources provides the mapping of mux position to the
* clock, and @reg_src shows the code where to modify to change the mux
* position. The @reg_div defines how to change the divider settings on
* the output.
*/
struct clksrc_clk {
struct clk clk;
struct clksrc_sources *sources;
struct clksrc_reg reg_src;
struct clksrc_reg reg_div;
};
/**
* s3c_set_clksrc() - setup the clock from the register settings
* @clk: The clock to setup.
* @announce: true to announce the setting to printk().
*
* Setup the clock from the current register settings, for when the
* kernel boots or if it is resuming from a possibly unknown state.
*/
extern void s3c_set_clksrc(struct clksrc_clk *clk, bool announce);
/**
* s3c_register_clksrc() register clocks from an array of clksrc clocks
* @srcs: The array of clocks to register
* @size: The size of the @srcs array.
*
* Initialise and register the array of clocks described by @srcs.
*/
extern void s3c_register_clksrc(struct clksrc_clk *srcs, int size);

View File

@@ -0,0 +1,156 @@
/* linux/arch/arm/plat-s3c/include/plat/clock.h
*
* Copyright (c) 2004-2005 Simtec Electronics
* http://www.simtec.co.uk/products/SWLINUX/
* Written by Ben Dooks, <ben@simtec.co.uk>
*
* 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.
*/
#ifndef __ASM_PLAT_CLOCK_H
#define __ASM_PLAT_CLOCK_H __FILE__
#include <linux/spinlock.h>
#include <linux/clkdev.h>
struct clk;
/**
* struct clk_ops - standard clock operations
* @set_rate: set the clock rate, see clk_set_rate().
* @get_rate: get the clock rate, see clk_get_rate().
* @round_rate: round a given clock rate, see clk_round_rate().
* @set_parent: set the clock's parent, see clk_set_parent().
*
* Group the common clock implementations together so that we
* don't have to keep setting the same fields again. We leave
* enable in struct clk.
*
* Adding an extra layer of indirection into the process should
* not be a problem as it is unlikely these operations are going
* to need to be called quickly.
*/
struct clk_ops {
int (*set_rate)(struct clk *c, unsigned long rate);
unsigned long (*get_rate)(struct clk *c);
unsigned long (*round_rate)(struct clk *c, unsigned long rate);
int (*set_parent)(struct clk *c, struct clk *parent);
};
struct clk {
struct list_head list;
struct module *owner;
struct clk *parent;
const char *name;
const char *devname;
int id;
int usage;
unsigned long rate;
unsigned long ctrlbit;
struct clk_ops *ops;
int (*enable)(struct clk *, int enable);
struct clk_lookup lookup;
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
struct dentry *dent; /* For visible tree hierarchy */
#endif
};
/* other clocks which may be registered by board support */
extern struct clk s3c24xx_dclk0;
extern struct clk s3c24xx_dclk1;
extern struct clk s3c24xx_clkout0;
extern struct clk s3c24xx_clkout1;
extern struct clk s3c24xx_uclk;
extern struct clk clk_usb_bus;
/* core clock support */
extern struct clk clk_f;
extern struct clk clk_h;
extern struct clk clk_p;
extern struct clk clk_mpll;
extern struct clk clk_upll;
extern struct clk clk_epll;
extern struct clk clk_xtal;
extern struct clk clk_ext;
/* S3C2443/S3C2416 specific clocks */
extern struct clksrc_clk clk_epllref;
extern struct clksrc_clk clk_esysclk;
/* S3C24XX UART clocks */
extern struct clk s3c24xx_clk_uart0;
extern struct clk s3c24xx_clk_uart1;
extern struct clk s3c24xx_clk_uart2;
/* S3C64XX specific clocks */
extern struct clk clk_h2;
extern struct clk clk_27m;
extern struct clk clk_48m;
extern struct clk clk_xusbxti;
extern int clk_default_setrate(struct clk *clk, unsigned long rate);
extern struct clk_ops clk_ops_def_setrate;
/* exports for arch/arm/mach-s3c2410
*
* Please DO NOT use these outside of arch/arm/mach-s3c2410
*/
extern spinlock_t clocks_lock;
extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
extern int s3c24xx_register_clock(struct clk *clk);
extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks);
extern void s3c_register_clocks(struct clk *clk, int nr_clks);
extern void s3c_disable_clocks(struct clk *clkp, int nr_clks);
extern int s3c24xx_register_baseclocks(unsigned long xtal);
extern void s5p_register_clocks(unsigned long xtal_freq);
extern void s3c24xx_setup_clocks(unsigned long fclk,
unsigned long hclk,
unsigned long pclk);
extern void s3c2410_setup_clocks(void);
extern void s3c2412_setup_clocks(void);
extern void s3c244x_setup_clocks(void);
/* S3C2410 specific clock functions */
extern int s3c2410_baseclk_add(void);
/* S3C2443/S3C2416 specific clock functions */
typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base);
extern void s3c2443_common_setup_clocks(pll_fn get_mpll);
extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
unsigned int *divs, int nr_divs,
int divmask);
extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable);
extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable);
extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable);
/* S3C64XX specific functions and clocks */
extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable);
/* Init for pwm clock code */
extern void s3c_pwmclk_init(void);
/* Global watchdog clock used by arch_wtd_reset() callback */
extern struct clk *s3c2410_wdtclk;
#endif /* __ASM_PLAT_CLOCK_H */

View File

@@ -0,0 +1,293 @@
/* arch/arm/plat-samsung/include/plat/cpu-freq-core.h
*
* Copyright (c) 2006-2009 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C CPU frequency scaling support - core support
*
* 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 <plat/cpu-freq.h>
struct seq_file;
#define MAX_BANKS (8)
#define S3C2412_MAX_IO (8)
/**
* struct s3c2410_iobank_timing - IO bank timings for S3C2410 style timings
* @bankcon: The cached version of settings in this structure.
* @tacp:
* @tacs: Time from address valid to nCS asserted.
* @tcos: Time from nCS asserted to nOE or nWE asserted.
* @tacc: Time that nOE or nWE is asserted.
* @tcoh: Time nCS is held after nOE or nWE are released.
* @tcah: Time address is held for after
* @nwait_en: Whether nWAIT is enabled for this bank.
*
* This structure represents the IO timings for a S3C2410 style IO bank
* used by the CPU frequency support if it needs to change the settings
* of the IO.
*/
struct s3c2410_iobank_timing {
unsigned long bankcon;
unsigned int tacp;
unsigned int tacs;
unsigned int tcos;
unsigned int tacc;
unsigned int tcoh; /* nCS hold afrer nOE/nWE */
unsigned int tcah; /* Address hold after nCS */
unsigned char nwait_en; /* nWait enabled for bank. */
};
/**
* struct s3c2412_iobank_timing - io timings for PL092 (S3C2412) style IO
* @idcy: The idle cycle time between transactions.
* @wstrd: nCS release to end of read cycle.
* @wstwr: nCS release to end of write cycle.
* @wstoen: nCS assertion to nOE assertion time.
* @wstwen: nCS assertion to nWE assertion time.
* @wstbrd: Burst ready delay.
* @smbidcyr: Register cache for smbidcyr value.
* @smbwstrd: Register cache for smbwstrd value.
* @smbwstwr: Register cache for smbwstwr value.
* @smbwstoen: Register cache for smbwstoen value.
* @smbwstwen: Register cache for smbwstwen value.
* @smbwstbrd: Register cache for smbwstbrd value.
*
* Timing information for a IO bank on an S3C2412 or similar system which
* uses a PL093 block.
*/
struct s3c2412_iobank_timing {
unsigned int idcy;
unsigned int wstrd;
unsigned int wstwr;
unsigned int wstoen;
unsigned int wstwen;
unsigned int wstbrd;
/* register cache */
unsigned char smbidcyr;
unsigned char smbwstrd;
unsigned char smbwstwr;
unsigned char smbwstoen;
unsigned char smbwstwen;
unsigned char smbwstbrd;
};
union s3c_iobank {
struct s3c2410_iobank_timing *io_2410;
struct s3c2412_iobank_timing *io_2412;
};
/**
* struct s3c_iotimings - Chip IO timings holder
* @bank: The timings for each IO bank.
*/
struct s3c_iotimings {
union s3c_iobank bank[MAX_BANKS];
};
/**
* struct s3c_plltab - PLL table information.
* @vals: List of PLL values.
* @size: Size of the PLL table @vals.
*/
struct s3c_plltab {
struct s3c_pllval *vals;
int size;
};
/**
* struct s3c_cpufreq_config - current cpu frequency configuration
* @freq: The current settings for the core clocks.
* @max: Maxium settings, derived from core, board and user settings.
* @pll: The PLL table entry for the current PLL settings.
* @divs: The divisor settings for the core clocks.
* @info: The current core driver information.
* @board: The information for the board we are running on.
* @lock_pll: Set if the PLL settings cannot be changed.
*
* This is for the core drivers that need to know information about
* the current settings and values. It should not be needed by any
* device drivers.
*/
struct s3c_cpufreq_config {
struct s3c_freq freq;
struct s3c_freq max;
struct cpufreq_frequency_table pll;
struct s3c_clkdivs divs;
struct s3c_cpufreq_info *info; /* for core, not drivers */
struct s3c_cpufreq_board *board;
unsigned int lock_pll:1;
};
/**
* struct s3c_cpufreq_info - Information for the CPU frequency driver.
* @name: The name of this implementation.
* @max: The maximum frequencies for the system.
* @latency: Transition latency to give to cpufreq.
* @locktime_m: The lock-time in uS for the MPLL.
* @locktime_u: The lock-time in uS for the UPLL.
* @locttime_bits: The number of bits each LOCKTIME field.
* @need_pll: Set if this driver needs to change the PLL values to achieve
* any frequency changes. This is really only need by devices like the
* S3C2410 where there is no or limited divider between the PLL and the
* ARMCLK.
* @resume_clocks: Update the clocks on resume.
* @get_iotiming: Get the current IO timing data, mainly for use at start.
* @set_iotiming: Update the IO timings from the cached copies calculated
* from the @calc_iotiming entry when changing the frequency.
* @calc_iotiming: Calculate and update the cached copies of the IO timings
* from the newly calculated frequencies.
* @calc_freqtable: Calculate (fill in) the given frequency table from the
* current frequency configuration. If the table passed in is NULL,
* then the return is the number of elements to be filled for allocation
* of the table.
* @set_refresh: Set the memory refresh configuration.
* @set_fvco: Set the PLL frequencies.
* @set_divs: Update the clock divisors.
* @calc_divs: Calculate the clock divisors.
*/
struct s3c_cpufreq_info {
const char *name;
struct s3c_freq max;
unsigned int latency;
unsigned int locktime_m;
unsigned int locktime_u;
unsigned char locktime_bits;
unsigned int need_pll:1;
/* driver routines */
void (*resume_clocks)(void);
int (*get_iotiming)(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *timings);
void (*set_iotiming)(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *timings);
int (*calc_iotiming)(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *timings);
int (*calc_freqtable)(struct s3c_cpufreq_config *cfg,
struct cpufreq_frequency_table *t,
size_t table_size);
void (*debug_io_show)(struct seq_file *seq,
struct s3c_cpufreq_config *cfg,
union s3c_iobank *iob);
void (*set_refresh)(struct s3c_cpufreq_config *cfg);
void (*set_fvco)(struct s3c_cpufreq_config *cfg);
void (*set_divs)(struct s3c_cpufreq_config *cfg);
int (*calc_divs)(struct s3c_cpufreq_config *cfg);
};
extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info);
extern int s3c_plltab_register(struct cpufreq_frequency_table *plls,
unsigned int plls_no);
/* exports and utilities for debugfs */
extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void);
extern struct s3c_iotimings *s3c_cpufreq_getiotimings(void);
#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS
#define s3c_cpufreq_debugfs_call(x) x
#else
#define s3c_cpufreq_debugfs_call(x) NULL
#endif
/* Useful utility functions. */
extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *);
/* S3C2410 and compatible exported functions */
extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg);
extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
#ifdef CONFIG_S3C2410_IOTIMING
extern void s3c2410_iotiming_debugfs(struct seq_file *seq,
struct s3c_cpufreq_config *cfg,
union s3c_iobank *iob);
extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *iot);
extern int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *timings);
extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *iot);
#else
#define s3c2410_iotiming_debugfs NULL
#define s3c2410_iotiming_calc NULL
#define s3c2410_iotiming_get NULL
#define s3c2410_iotiming_set NULL
#endif /* CONFIG_S3C2410_IOTIMING */
/* S3C2412 compatible routines */
#ifdef CONFIG_S3C2412_IOTIMING
extern void s3c2412_iotiming_debugfs(struct seq_file *seq,
struct s3c_cpufreq_config *cfg,
union s3c_iobank *iob);
extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *timings);
extern int s3c2412_iotiming_calc(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *iot);
extern void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *iot);
#else
#define s3c2412_iotiming_debugfs NULL
#define s3c2412_iotiming_calc NULL
#define s3c2412_iotiming_get NULL
#define s3c2412_iotiming_set NULL
#endif /* CONFIG_S3C2412_IOTIMING */
#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUG
#define s3c_freq_dbg(x...) printk(KERN_INFO x)
#else
#define s3c_freq_dbg(x...) do { if (0) printk(x); } while (0)
#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUG */
#ifdef CONFIG_CPU_FREQ_S3C24XX_IODEBUG
#define s3c_freq_iodbg(x...) printk(KERN_INFO x)
#else
#define s3c_freq_iodbg(x...) do { if (0) printk(x); } while (0)
#endif /* CONFIG_CPU_FREQ_S3C24XX_IODEBUG */
static inline int s3c_cpufreq_addfreq(struct cpufreq_frequency_table *table,
int index, size_t table_size,
unsigned int freq)
{
if (index < 0)
return index;
if (table) {
if (index >= table_size)
return -ENOMEM;
s3c_freq_dbg("%s: { %d = %u kHz }\n",
__func__, index, freq);
table[index].index = index;
table[index].frequency = freq;
}
return index + 1;
}

View File

@@ -0,0 +1,145 @@
/* arch/arm/plat-samsung/include/plat/cpu-freq.h
*
* Copyright (c) 2006-2007 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C CPU frequency scaling support - driver and board
*
* 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/cpufreq.h>
struct s3c_cpufreq_info;
struct s3c_cpufreq_board;
struct s3c_iotimings;
/**
* struct s3c_freq - frequency information (mainly for core drivers)
* @fclk: The FCLK frequency in Hz.
* @armclk: The ARMCLK frequency in Hz.
* @hclk_tns: HCLK cycle time in 10ths of nano-seconds.
* @hclk: The HCLK frequency in Hz.
* @pclk: The PCLK frequency in Hz.
*
* This contains the frequency information about the current configuration
* mainly for the core drivers to ensure we do not end up passing about
* a large number of parameters.
*
* The @hclk_tns field is a useful cache for the parts of the drivers that
* need to calculate IO timings and suchlike.
*/
struct s3c_freq {
unsigned long fclk;
unsigned long armclk;
unsigned long hclk_tns; /* in 10ths of ns */
unsigned long hclk;
unsigned long pclk;
};
/**
* struct s3c_cpufreq_freqs - s3c cpufreq notification information.
* @freqs: The cpufreq setting information.
* @old: The old clock settings.
* @new: The new clock settings.
* @pll_changing: Set if the PLL is changing.
*
* Wrapper 'struct cpufreq_freqs' so that any drivers receiving the
* notification can use this information that is not provided by just
* having the core frequency alone.
*
* The pll_changing flag is used to indicate if the PLL itself is
* being set during this change. This is important as the clocks
* will temporarily be set to the XTAL clock during this time, so
* drivers may want to close down their output during this time.
*
* Note, this is not being used by any current drivers and therefore
* may be removed in the future.
*/
struct s3c_cpufreq_freqs {
struct cpufreq_freqs freqs;
struct s3c_freq old;
struct s3c_freq new;
unsigned int pll_changing:1;
};
#define to_s3c_cpufreq(_cf) container_of(_cf, struct s3c_cpufreq_freqs, freqs)
/**
* struct s3c_clkdivs - clock divisor information
* @p_divisor: Divisor from FCLK to PCLK.
* @h_divisor: Divisor from FCLK to HCLK.
* @arm_divisor: Divisor from FCLK to ARMCLK (not all CPUs).
* @dvs: Non-zero if using DVS mode for ARMCLK.
*
* Divisor settings for the core clocks.
*/
struct s3c_clkdivs {
int p_divisor;
int h_divisor;
int arm_divisor;
unsigned char dvs;
};
#define PLLVAL(_m, _p, _s) (((_m) << 12) | ((_p) << 4) | (_s))
/**
* struct s3c_pllval - PLL value entry.
* @freq: The frequency for this entry in Hz.
* @pll_reg: The PLL register setting for this PLL value.
*/
struct s3c_pllval {
unsigned long freq;
unsigned long pll_reg;
};
/**
* struct s3c_cpufreq_board - per-board cpu frequency informatin
* @refresh: The SDRAM refresh period in nanoseconds.
* @auto_io: Set if the IO timing settings should be generated from the
* initialisation time hardware registers.
* @need_io: Set if the board has external IO on any of the chipselect
* lines that will require the hardware timing registers to be
* updated on a clock change.
* @max: The maxium frequency limits for the system. Any field that
* is left at zero will use the CPU's settings.
*
* This contains the board specific settings that affect how the CPU
* drivers chose settings. These include the memory refresh and IO
* timing information.
*
* Registration depends on the driver being used, the ARMCLK only
* implementation does not currently need this but the older style
* driver requires this to be available.
*/
struct s3c_cpufreq_board {
unsigned int refresh;
unsigned int auto_io:1; /* automatically init io timings. */
unsigned int need_io:1; /* set if needs io timing support. */
/* any non-zero field in here is taken as an upper limit. */
struct s3c_freq max; /* frequency limits */
};
/* Things depending on frequency scaling. */
#ifdef CONFIG_CPU_FREQ_S3C
#define __init_or_cpufreq
#else
#define __init_or_cpufreq __init
#endif
/* Board functions */
#ifdef CONFIG_CPU_FREQ_S3C
extern int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board);
#else
static inline int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board)
{
return 0;
}
#endif /* CONFIG_CPU_FREQ_S3C */

View File

@@ -0,0 +1,225 @@
/* linux/arch/arm/plat-samsung/include/plat/cpu.h
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* Copyright (c) 2004-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Header file for Samsung CPU support
*
* 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.
*/
/* todo - fix when rmk changes iodescs to use `void __iomem *` */
#ifndef __SAMSUNG_PLAT_CPU_H
#define __SAMSUNG_PLAT_CPU_H
extern unsigned long samsung_cpu_id;
#define S3C24XX_CPU_ID 0x32400000
#define S3C24XX_CPU_MASK 0xFFF00000
#define S3C2412_CPU_ID 0x32412000
#define S3C2412_CPU_MASK 0xFFFFF000
#define S3C6400_CPU_ID 0x36400000
#define S3C6410_CPU_ID 0x36410000
#define S3C64XX_CPU_MASK 0xFFFFF000
#define S5P6440_CPU_ID 0x56440000
#define S5P6450_CPU_ID 0x36450000
#define S5P64XX_CPU_MASK 0xFFFFF000
#define S5PC100_CPU_ID 0x43100000
#define S5PC100_CPU_MASK 0xFFFFF000
#define S5PV210_CPU_ID 0x43110000
#define S5PV210_CPU_MASK 0xFFFFF000
#define EXYNOS4210_CPU_ID 0x43210000
#define EXYNOS4212_CPU_ID 0x43220000
#define EXYNOS4412_CPU_ID 0xE4412200
#define EXYNOS4_CPU_MASK 0xFFFE0000
#define EXYNOS5250_SOC_ID 0x43520000
#define EXYNOS5440_SOC_ID 0xE5440000
#define EXYNOS5_SOC_MASK 0xFFFFF000
#define IS_SAMSUNG_CPU(name, id, mask) \
static inline int is_samsung_##name(void) \
{ \
return ((samsung_cpu_id & mask) == (id & mask)); \
}
IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK)
IS_SAMSUNG_CPU(s3c2412, S3C2412_CPU_ID, S3C2412_CPU_MASK)
IS_SAMSUNG_CPU(s3c6400, S3C6400_CPU_ID, S3C64XX_CPU_MASK)
IS_SAMSUNG_CPU(s3c6410, S3C6410_CPU_ID, S3C64XX_CPU_MASK)
IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK)
IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK)
IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK)
IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK)
IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \
defined(CONFIG_CPU_S3C2442) || defined(CONFIG_CPU_S3C244X) || \
defined(CONFIG_CPU_S3C2443)
# define soc_is_s3c24xx() is_samsung_s3c24xx()
#else
# define soc_is_s3c24xx() 0
#endif
#if defined(CONFIG_CPU_S3C2412)
# define soc_is_s3c2412() is_samsung_s3c2412()
#else
# define soc_is_s3c2412() 0
#endif
#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
# define soc_is_s3c64xx() (is_samsung_s3c6400() || is_samsung_s3c6410())
#else
# define soc_is_s3c64xx() 0
#endif
#if defined(CONFIG_CPU_S5P6440)
# define soc_is_s5p6440() is_samsung_s5p6440()
#else
# define soc_is_s5p6440() 0
#endif
#if defined(CONFIG_CPU_S5P6450)
# define soc_is_s5p6450() is_samsung_s5p6450()
#else
# define soc_is_s5p6450() 0
#endif
#if defined(CONFIG_CPU_S5PC100)
# define soc_is_s5pc100() is_samsung_s5pc100()
#else
# define soc_is_s5pc100() 0
#endif
#if defined(CONFIG_CPU_S5PV210)
# define soc_is_s5pv210() is_samsung_s5pv210()
#else
# define soc_is_s5pv210() 0
#endif
#if defined(CONFIG_CPU_EXYNOS4210)
# define soc_is_exynos4210() is_samsung_exynos4210()
#else
# define soc_is_exynos4210() 0
#endif
#if defined(CONFIG_SOC_EXYNOS4212)
# define soc_is_exynos4212() is_samsung_exynos4212()
#else
# define soc_is_exynos4212() 0
#endif
#if defined(CONFIG_SOC_EXYNOS4412)
# define soc_is_exynos4412() is_samsung_exynos4412()
#else
# define soc_is_exynos4412() 0
#endif
#define EXYNOS4210_REV_0 (0x0)
#define EXYNOS4210_REV_1_0 (0x10)
#define EXYNOS4210_REV_1_1 (0x11)
#if defined(CONFIG_SOC_EXYNOS5250)
# define soc_is_exynos5250() is_samsung_exynos5250()
#else
# define soc_is_exynos5250() 0
#endif
#if defined(CONFIG_SOC_EXYNOS5440)
# define soc_is_exynos5440() is_samsung_exynos5440()
#else
# define soc_is_exynos5440() 0
#endif
#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
#ifndef KHZ
#define KHZ (1000)
#endif
#ifndef MHZ
#define MHZ (1000*1000)
#endif
#define print_mhz(m) ((m) / MHZ), (((m) / 1000) % 1000)
/* forward declaration */
struct s3c24xx_uart_resources;
struct platform_device;
struct s3c2410_uartcfg;
struct map_desc;
/* per-cpu initialisation function table. */
struct cpu_table {
unsigned long idcode;
unsigned long idmask;
void (*map_io)(void);
void (*init_uarts)(struct s3c2410_uartcfg *cfg, int no);
void (*init_clocks)(int xtal);
int (*init)(void);
const char *name;
};
extern void s3c_init_cpu(unsigned long idcode,
struct cpu_table *cpus, unsigned int cputab_size);
/* core initialisation functions */
extern void s5p_init_irq(u32 *vic, u32 num_vic);
extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
extern void s3c24xx_init_cpu(void);
extern void s3c64xx_init_cpu(void);
extern void s5p_init_cpu(void __iomem *cpuid_addr);
extern unsigned int samsung_rev(void);
extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
extern void s3c24xx_init_clocks(int xtal);
extern void s3c24xx_init_uartdevs(char *name,
struct s3c24xx_uart_resources *res,
struct s3c2410_uartcfg *cfg, int no);
extern struct syscore_ops s3c2410_pm_syscore_ops;
extern struct syscore_ops s3c2412_pm_syscore_ops;
extern struct syscore_ops s3c2416_pm_syscore_ops;
extern struct syscore_ops s3c244x_pm_syscore_ops;
/* system device subsystems */
extern struct bus_type s3c2410_subsys;
extern struct bus_type s3c2410a_subsys;
extern struct bus_type s3c2412_subsys;
extern struct bus_type s3c2416_subsys;
extern struct bus_type s3c2440_subsys;
extern struct bus_type s3c2442_subsys;
extern struct bus_type s3c2443_subsys;
extern struct bus_type s3c6410_subsys;
extern struct bus_type s5p64x0_subsys;
extern struct bus_type s5pv210_subsys;
extern struct bus_type exynos_subsys;
extern void (*s5pc1xx_idle)(void);
#endif

View File

@@ -0,0 +1,159 @@
/* arch/arm/plat-samsung/include/plat/devs.h
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Header file for s3c2410 standard platform devices
*
* 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.
*/
#ifndef __PLAT_DEVS_H
#define __PLAT_DEVS_H __FILE__
#include <linux/platform_device.h>
struct s3c24xx_uart_resources {
struct resource *resources;
unsigned long nr_resources;
};
extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
extern struct s3c24xx_uart_resources s5p_uart_resources[];
extern struct s3c24xx_uart_resources exynos4_uart_resources[];
extern struct s3c24xx_uart_resources exynos5_uart_resources[];
extern struct platform_device *s3c24xx_uart_devs[];
extern struct platform_device *s3c24xx_uart_src[];
extern struct platform_device s3c64xx_device_ac97;
extern struct platform_device s3c64xx_device_iis0;
extern struct platform_device s3c64xx_device_iis1;
extern struct platform_device s3c64xx_device_iisv4;
extern struct platform_device s3c64xx_device_onenand1;
extern struct platform_device s3c64xx_device_pcm0;
extern struct platform_device s3c64xx_device_pcm1;
extern struct platform_device s3c64xx_device_spi0;
extern struct platform_device s3c64xx_device_spi1;
extern struct platform_device s3c64xx_device_spi2;
extern struct platform_device s3c_device_adc;
extern struct platform_device s3c_device_cfcon;
extern struct platform_device s3c_device_fb;
extern struct platform_device s3c_device_hwmon;
extern struct platform_device s3c_device_hsmmc0;
extern struct platform_device s3c_device_hsmmc1;
extern struct platform_device s3c_device_hsmmc2;
extern struct platform_device s3c_device_hsmmc3;
extern struct platform_device s3c_device_i2c0;
extern struct platform_device s3c_device_i2c1;
extern struct platform_device s3c_device_i2c2;
extern struct platform_device s3c_device_i2c3;
extern struct platform_device s3c_device_i2c4;
extern struct platform_device s3c_device_i2c5;
extern struct platform_device s3c_device_i2c6;
extern struct platform_device s3c_device_i2c7;
extern struct platform_device s3c_device_iis;
extern struct platform_device s3c_device_lcd;
extern struct platform_device s3c_device_nand;
extern struct platform_device s3c_device_ohci;
extern struct platform_device s3c_device_onenand;
extern struct platform_device s3c_device_rtc;
extern struct platform_device s3c_device_sdi;
extern struct platform_device s3c_device_spi0;
extern struct platform_device s3c_device_spi1;
extern struct platform_device s3c_device_ts;
extern struct platform_device s3c_device_timer[];
extern struct platform_device s3c_device_usbgadget;
extern struct platform_device s3c_device_usb_hsotg;
extern struct platform_device s3c_device_usb_hsudc;
extern struct platform_device s3c_device_wdt;
extern struct platform_device s5p_device_ehci;
extern struct platform_device s5p_device_fimc0;
extern struct platform_device s5p_device_fimc1;
extern struct platform_device s5p_device_fimc2;
extern struct platform_device s5p_device_fimc3;
extern struct platform_device s5p_device_fimc_md;
extern struct platform_device s5p_device_jpeg;
extern struct platform_device s5p_device_g2d;
extern struct platform_device s5p_device_fimd0;
extern struct platform_device s5p_device_hdmi;
extern struct platform_device s5p_device_i2c_hdmiphy;
extern struct platform_device s5p_device_mfc;
extern struct platform_device s5p_device_mfc_l;
extern struct platform_device s5p_device_mfc_r;
extern struct platform_device s5p_device_mipi_csis0;
extern struct platform_device s5p_device_mipi_csis1;
extern struct platform_device s5p_device_mixer;
extern struct platform_device s5p_device_onenand;
extern struct platform_device s5p_device_sdo;
extern struct platform_device s5p6440_device_iis;
extern struct platform_device s5p6440_device_pcm;
extern struct platform_device s5p6450_device_iis0;
extern struct platform_device s5p6450_device_iis1;
extern struct platform_device s5p6450_device_iis2;
extern struct platform_device s5p6450_device_pcm0;
extern struct platform_device s5pc100_device_ac97;
extern struct platform_device s5pc100_device_iis0;
extern struct platform_device s5pc100_device_iis1;
extern struct platform_device s5pc100_device_iis2;
extern struct platform_device s5pc100_device_pcm0;
extern struct platform_device s5pc100_device_pcm1;
extern struct platform_device s5pc100_device_spdif;
extern struct platform_device s5pv210_device_ac97;
extern struct platform_device s5pv210_device_iis0;
extern struct platform_device s5pv210_device_iis1;
extern struct platform_device s5pv210_device_iis2;
extern struct platform_device s5pv210_device_pcm0;
extern struct platform_device s5pv210_device_pcm1;
extern struct platform_device s5pv210_device_pcm2;
extern struct platform_device s5pv210_device_spdif;
extern struct platform_device exynos4_device_ac97;
extern struct platform_device exynos4_device_ahci;
extern struct platform_device exynos4_device_i2s0;
extern struct platform_device exynos4_device_i2s1;
extern struct platform_device exynos4_device_i2s2;
extern struct platform_device exynos4_device_ohci;
extern struct platform_device exynos4_device_pcm0;
extern struct platform_device exynos4_device_pcm1;
extern struct platform_device exynos4_device_pcm2;
extern struct platform_device exynos4_device_spdif;
extern struct platform_device samsung_asoc_idma;
extern struct platform_device samsung_device_keypad;
/* s3c2440 specific devices */
#ifdef CONFIG_CPU_S3C2440
extern struct platform_device s3c_device_camif;
extern struct platform_device s3c_device_ac97;
#endif
/**
* s3c_set_platdata() - helper for setting platform data
* @pd: The default platform data for this device.
* @pdsize: The size of the platform data.
* @pdev: Pointer to the device to fill in.
*
* This helper replaces a number of calls that copy and then set the
* platform data of the device.
*/
extern void *s3c_set_platdata(void *pd, size_t pdsize,
struct platform_device *pdev);
#endif /* __PLAT_DEVS_H */

View File

@@ -0,0 +1,22 @@
/* arch/arm/plat-s3c/include/plat/dma.h
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* Samsung S3C DMA core support
*
* 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.
*/
extern struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel);
extern struct s3c2410_dma_chan *s3c_dma_chan_map[];
/* the currently allocated channel information */
extern struct s3c2410_dma_chan s3c2410_chans[];

View File

@@ -0,0 +1,69 @@
/* arch/arm/plat-samsung/include/plat/dma-ops.h
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung DMA support
*
* 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.
*/
#ifndef __SAMSUNG_DMA_OPS_H_
#define __SAMSUNG_DMA_OPS_H_ __FILE__
#include <linux/dmaengine.h>
#include <mach/dma.h>
struct samsung_dma_req {
enum dma_transaction_type cap;
struct s3c2410_dma_client *client;
};
struct samsung_dma_prep {
enum dma_transaction_type cap;
enum dma_transfer_direction direction;
dma_addr_t buf;
unsigned long period;
unsigned long len;
void (*fp)(void *data);
void *fp_param;
};
struct samsung_dma_config {
enum dma_transfer_direction direction;
enum dma_slave_buswidth width;
dma_addr_t fifo;
};
struct samsung_dma_ops {
unsigned (*request)(enum dma_ch ch, struct samsung_dma_req *param,
struct device *dev, char *ch_name);
int (*release)(unsigned ch, void *param);
int (*config)(unsigned ch, struct samsung_dma_config *param);
int (*prepare)(unsigned ch, struct samsung_dma_prep *param);
int (*trigger)(unsigned ch);
int (*started)(unsigned ch);
int (*flush)(unsigned ch);
int (*stop)(unsigned ch);
};
extern void *samsung_dmadev_get_ops(void);
extern void *s3c_dma_get_ops(void);
static inline void *__samsung_dma_get_ops(void)
{
if (samsung_dma_is_dmadev())
return samsung_dmadev_get_ops();
else
return s3c_dma_get_ops();
}
/*
* samsung_dma_get_ops
* get the set of samsung dma operations
*/
#define samsung_dma_get_ops() __samsung_dma_get_ops()
#endif /* __SAMSUNG_DMA_OPS_H_ */

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
* Jaswinder Singh <jassi.brar@samsung.com>
*
* 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.
*/
#ifndef __DMA_PL330_H_
#define __DMA_PL330_H_ __FILE__
/*
* PL330 can assign any channel to communicate with
* any of the peripherals attched to the DMAC.
* For the sake of consistency across client drivers,
* We keep the channel names unchanged and only add
* missing peripherals are added.
* Order is not important since DMA PL330 API driver
* use these just as IDs.
*/
enum dma_ch {
DMACH_UART0_RX = 0,
DMACH_UART0_TX,
DMACH_UART1_RX,
DMACH_UART1_TX,
DMACH_UART2_RX,
DMACH_UART2_TX,
DMACH_UART3_RX,
DMACH_UART3_TX,
DMACH_UART4_RX,
DMACH_UART4_TX,
DMACH_UART5_RX,
DMACH_UART5_TX,
DMACH_USI_RX,
DMACH_USI_TX,
DMACH_IRDA,
DMACH_I2S0_RX,
DMACH_I2S0_TX,
DMACH_I2S0S_TX,
DMACH_I2S1_RX,
DMACH_I2S1_TX,
DMACH_I2S2_RX,
DMACH_I2S2_TX,
DMACH_SPI0_RX,
DMACH_SPI0_TX,
DMACH_SPI1_RX,
DMACH_SPI1_TX,
DMACH_SPI2_RX,
DMACH_SPI2_TX,
DMACH_AC97_MICIN,
DMACH_AC97_PCMIN,
DMACH_AC97_PCMOUT,
DMACH_EXTERNAL,
DMACH_PWM,
DMACH_SPDIF,
DMACH_HSI_RX,
DMACH_HSI_TX,
DMACH_PCM0_TX,
DMACH_PCM0_RX,
DMACH_PCM1_TX,
DMACH_PCM1_RX,
DMACH_PCM2_TX,
DMACH_PCM2_RX,
DMACH_MSM_REQ3,
DMACH_MSM_REQ2,
DMACH_MSM_REQ1,
DMACH_MSM_REQ0,
DMACH_SLIMBUS0_RX,
DMACH_SLIMBUS0_TX,
DMACH_SLIMBUS0AUX_RX,
DMACH_SLIMBUS0AUX_TX,
DMACH_SLIMBUS1_RX,
DMACH_SLIMBUS1_TX,
DMACH_SLIMBUS2_RX,
DMACH_SLIMBUS2_TX,
DMACH_SLIMBUS3_RX,
DMACH_SLIMBUS3_TX,
DMACH_SLIMBUS4_RX,
DMACH_SLIMBUS4_TX,
DMACH_SLIMBUS5_RX,
DMACH_SLIMBUS5_TX,
DMACH_MIPI_HSI0,
DMACH_MIPI_HSI1,
DMACH_MIPI_HSI2,
DMACH_MIPI_HSI3,
DMACH_MIPI_HSI4,
DMACH_MIPI_HSI5,
DMACH_MIPI_HSI6,
DMACH_MIPI_HSI7,
DMACH_DISP1,
DMACH_MTOM_0,
DMACH_MTOM_1,
DMACH_MTOM_2,
DMACH_MTOM_3,
DMACH_MTOM_4,
DMACH_MTOM_5,
DMACH_MTOM_6,
DMACH_MTOM_7,
/* END Marker, also used to denote a reserved channel */
DMACH_MAX,
};
struct s3c2410_dma_client {
char *name;
};
static inline bool samsung_dma_has_circular(void)
{
return true;
}
static inline bool samsung_dma_is_dmadev(void)
{
return true;
}
#include <plat/dma-ops.h>
#endif /* __DMA_PL330_H_ */

View File

@@ -0,0 +1,78 @@
/* linux/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
*
* Copyright (C) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Samsung S3C24XX DMA support - per SoC functions
*
* 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 <plat/dma-core.h>
extern struct bus_type dma_subsys;
extern struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
#define DMA_CH_VALID (1<<31)
#define DMA_CH_NEVER (1<<30)
/* struct s3c24xx_dma_map
*
* this holds the mapping information for the channel selected
* to be connected to the specified device
*/
struct s3c24xx_dma_map {
const char *name;
unsigned long channels[S3C_DMA_CHANNELS];
unsigned long channels_rx[S3C_DMA_CHANNELS];
};
struct s3c24xx_dma_selection {
struct s3c24xx_dma_map *map;
unsigned long map_size;
unsigned long dcon_mask;
void (*select)(struct s3c2410_dma_chan *chan,
struct s3c24xx_dma_map *map);
void (*direction)(struct s3c2410_dma_chan *chan,
struct s3c24xx_dma_map *map,
enum dma_data_direction dir);
};
extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
/* struct s3c24xx_dma_order_ch
*
* channel map for one of the `enum dma_ch` dma channels. the list
* entry contains a set of low-level channel numbers, orred with
* DMA_CH_VALID, which are checked in the order in the array.
*/
struct s3c24xx_dma_order_ch {
unsigned int list[S3C_DMA_CHANNELS]; /* list of channels */
unsigned int flags; /* flags */
};
/* struct s3c24xx_dma_order
*
* information provided by either the core or the board to give the
* dma system a hint on how to allocate channels
*/
struct s3c24xx_dma_order {
struct s3c24xx_dma_order_ch channels[DMACH_MAX];
};
extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
/* DMA init code, called from the cpu support code */
extern int s3c2410_dma_init(void);
extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
unsigned int stride);

View File

@@ -0,0 +1,130 @@
/* arch/arm/plat-samsung/include/plat/dma.h
*
* Copyright (C) 2003-2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Samsung S3C DMA support
*
* 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.
*/
#ifndef __PLAT_DMA_H
#define __PLAT_DMA_H
#include <linux/dma-mapping.h>
enum s3c2410_dma_buffresult {
S3C2410_RES_OK,
S3C2410_RES_ERR,
S3C2410_RES_ABORT
};
/* enum s3c2410_chan_op
*
* operation codes passed to the DMA code by the user, and also used
* to inform the current channel owner of any changes to the system state
*/
enum s3c2410_chan_op {
S3C2410_DMAOP_START,
S3C2410_DMAOP_STOP,
S3C2410_DMAOP_PAUSE,
S3C2410_DMAOP_RESUME,
S3C2410_DMAOP_FLUSH,
S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */
S3C2410_DMAOP_STARTED, /* indicate channel started */
};
struct s3c2410_dma_client {
char *name;
};
struct s3c2410_dma_chan;
enum dma_ch;
/* s3c2410_dma_cbfn_t
*
* buffer callback routine type
*/
typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
void *buf, int size,
enum s3c2410_dma_buffresult result);
typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
enum s3c2410_chan_op );
/* s3c2410_dma_request
*
* request a dma channel exclusivley
*/
extern int s3c2410_dma_request(enum dma_ch channel,
struct s3c2410_dma_client *, void *dev);
/* s3c2410_dma_ctrl
*
* change the state of the dma channel
*/
extern int s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op);
/* s3c2410_dma_setflags
*
* set the channel's flags to a given state
*/
extern int s3c2410_dma_setflags(enum dma_ch channel,
unsigned int flags);
/* s3c2410_dma_free
*
* free the dma channel (will also abort any outstanding operations)
*/
extern int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *);
/* s3c2410_dma_enqueue
*
* place the given buffer onto the queue of operations for the channel.
* The buffer must be allocated from dma coherent memory, or the Dcache/WB
* drained before the buffer is given to the DMA system.
*/
extern int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
dma_addr_t data, int size);
/* s3c2410_dma_config
*
* configure the dma channel
*/
extern int s3c2410_dma_config(enum dma_ch channel, int xferunit);
/* s3c2410_dma_devconfig
*
* configure the device we're talking to
*/
extern int s3c2410_dma_devconfig(enum dma_ch channel,
enum dma_data_direction source, unsigned long devaddr);
/* s3c2410_dma_getposition
*
* get the position that the dma transfer is currently at
*/
extern int s3c2410_dma_getposition(enum dma_ch channel,
dma_addr_t *src, dma_addr_t *dest);
extern int s3c2410_dma_set_opfn(enum dma_ch, s3c2410_dma_opfn_t rtn);
extern int s3c2410_dma_set_buffdone_fn(enum dma_ch, s3c2410_dma_cbfn_t rtn);
#include <plat/dma-ops.h>
#endif

View File

@@ -0,0 +1,44 @@
/*
* arch/arm/plat-samsung/include/plat/fb-core.h
*
* Copyright 2010 Samsung Electronics Co., Ltd.
* Pawel Osciak <p.osciak@samsung.com>
*
* Samsung framebuffer driver core functions
*
* 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.
*/
#ifndef __ASM_PLAT_FB_CORE_H
#define __ASM_PLAT_FB_CORE_H __FILE__
/*
* These functions are only for use with the core support code, such as
* the CPU-specific initialization code.
*/
/* Re-define device name depending on support. */
static inline void s3c_fb_setname(char *name)
{
#ifdef CONFIG_S3C_DEV_FB
s3c_device_fb.name = name;
#endif
}
/* Re-define device name depending on support. */
static inline void s5p_fb_setname(int id, char *name)
{
switch (id) {
#ifdef CONFIG_S5P_DEV_FIMD0
case 0:
s5p_device_fimd0.name = name;
break;
#endif
default:
printk(KERN_ERR "%s: invalid device id(%d)\n", __func__, id);
break;
}
}
#endif /* __ASM_PLAT_FB_CORE_H */

View File

@@ -0,0 +1,72 @@
/* arch/arm/plat-samsung/include/plat/fb-s3c2410.h
*
* Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
*
* Inspired by pxafb.h
*
* 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.
*/
#ifndef __ASM_PLAT_FB_S3C2410_H
#define __ASM_PLAT_FB_S3C2410_H __FILE__
struct s3c2410fb_hw {
unsigned long lcdcon1;
unsigned long lcdcon2;
unsigned long lcdcon3;
unsigned long lcdcon4;
unsigned long lcdcon5;
};
/* LCD description */
struct s3c2410fb_display {
/* LCD type */
unsigned type;
/* Screen size */
unsigned short width;
unsigned short height;
/* Screen info */
unsigned short xres;
unsigned short yres;
unsigned short bpp;
unsigned pixclock; /* pixclock in picoseconds */
unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */
unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */
unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */
unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */
/* lcd configuration registers */
unsigned long lcdcon5;
};
struct s3c2410fb_mach_info {
struct s3c2410fb_display *displays; /* attached diplays info */
unsigned num_displays; /* number of defined displays */
unsigned default_display;
/* GPIOs */
unsigned long gpcup;
unsigned long gpcup_mask;
unsigned long gpccon;
unsigned long gpccon_mask;
unsigned long gpdup;
unsigned long gpdup_mask;
unsigned long gpdcon;
unsigned long gpdcon_mask;
/* lpc3600 control register */
unsigned long lpcsel;
};
extern void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *);
#endif /* __ASM_PLAT_FB_S3C2410_H */

View File

@@ -0,0 +1,71 @@
/* arch/arm/plat-samsung/include/plat/fb.h
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C - FB platform data definitions
*
* 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.
*/
#ifndef __PLAT_S3C_FB_H
#define __PLAT_S3C_FB_H __FILE__
#include <linux/platform_data/video_s3c.h>
/**
* s3c_fb_set_platdata() - Setup the FB device with platform data.
* @pd: The platform data to set. The data is copied from the passed structure
* so the machine data can mark the data __initdata so that any unused
* machines will end up dumping their data at runtime.
*/
extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
/**
* s5p_fimd0_set_platdata() - Setup the FB device with platform data.
* @pd: The platform data to set. The data is copied from the passed structure
* so the machine data can mark the data __initdata so that any unused
* machines will end up dumping their data at runtime.
*/
extern void s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd);
/**
* s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
*
* Initialise the GPIO for an 24bpp LCD display on the RGB interface.
*/
extern void s3c64xx_fb_gpio_setup_24bpp(void);
/**
* s5pc100_fb_gpio_setup_24bpp() - S5PC100 setup function for 24bpp LCD
*
* Initialise the GPIO for an 24bpp LCD display on the RGB interface.
*/
extern void s5pc100_fb_gpio_setup_24bpp(void);
/**
* s5pv210_fb_gpio_setup_24bpp() - S5PV210/S5PC110 setup function for 24bpp LCD
*
* Initialise the GPIO for an 24bpp LCD display on the RGB interface.
*/
extern void s5pv210_fb_gpio_setup_24bpp(void);
/**
* exynos4_fimd0_gpio_setup_24bpp() - Exynos4 setup function for 24bpp LCD0
*
* Initialise the GPIO for an 24bpp LCD display on the RGB interface 0.
*/
extern void exynos4_fimd0_gpio_setup_24bpp(void);
/**
* s5p64x0_fb_gpio_setup_24bpp() - S5P6440/S5P6450 setup function for 24bpp LCD
*
* Initialise the GPIO for an 24bpp LCD display on the RGB interface.
*/
extern void s5p64x0_fb_gpio_setup_24bpp(void);
#endif /* __PLAT_S3C_FB_H */

View File

@@ -0,0 +1,51 @@
/*
* arch/arm/plat-samsung/include/plat/fimc-core.h
*
* Copyright 2010 Samsung Electronics Co., Ltd.
* Sylwester Nawrocki <s.nawrocki@samsung.com>
*
* Samsung camera interface driver core functions
*
* 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.
*/
#ifndef __ASM_PLAT_FIMC_CORE_H
#define __ASM_PLAT_FIMC_CORE_H __FILE__
/*
* These functions are only for use with the core support code, such as
* the CPU-specific initialization code.
*/
/* Re-define device name to differentiate the subsystem in various SoCs. */
static inline void s3c_fimc_setname(int id, char *name)
{
switch (id) {
#ifdef CONFIG_S5P_DEV_FIMC0
case 0:
s5p_device_fimc0.name = name;
break;
#endif
#ifdef CONFIG_S5P_DEV_FIMC1
case 1:
s5p_device_fimc1.name = name;
break;
#endif
#ifdef CONFIG_S5P_DEV_FIMC2
case 2:
s5p_device_fimc2.name = name;
break;
#endif
#ifdef CONFIG_S5P_DEV_FIMC3
case 3:
s5p_device_fimc3.name = name;
break;
#endif
default:
break;
}
}
#endif /* __ASM_PLAT_FIMC_CORE_H */

View File

@@ -0,0 +1,13 @@
/* linux/arch/arm/plat-samsung/include/plat/fiq.h
*
* Copyright (c) 2009 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Header file for S3C24XX CPU FIQ support
*
* 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.
*/
extern int s3c24xx_set_fiq(unsigned int irq, bool on);

View File

@@ -0,0 +1,163 @@
/* linux/arch/arm/plat-samsung/include/plat/gpio-cfg-helper.h
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* Samsung Platform - GPIO pin configuration helper definitions
*
* 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 is meant for core cpu support, machine or other driver files
* should not be including this header.
*/
#ifndef __PLAT_GPIO_CFG_HELPERS_H
#define __PLAT_GPIO_CFG_HELPERS_H __FILE__
/* As a note, all gpio configuration functions are entered exclusively, either
* with the relevant lock held or the system prevented from doing anything else
* by disabling interrupts.
*/
static inline int samsung_gpio_do_setcfg(struct samsung_gpio_chip *chip,
unsigned int off, unsigned int config)
{
return (chip->config->set_config)(chip, off, config);
}
static inline unsigned samsung_gpio_do_getcfg(struct samsung_gpio_chip *chip,
unsigned int off)
{
return (chip->config->get_config)(chip, off);
}
static inline int samsung_gpio_do_setpull(struct samsung_gpio_chip *chip,
unsigned int off, samsung_gpio_pull_t pull)
{
return (chip->config->set_pull)(chip, off, pull);
}
static inline samsung_gpio_pull_t samsung_gpio_do_getpull(struct samsung_gpio_chip *chip,
unsigned int off)
{
return chip->config->get_pull(chip, off);
}
/* Pull-{up,down} resistor controls.
*
* S3C2410,S3C2440 = Pull-UP,
* S3C2412,S3C2413 = Pull-Down
* S3C6400,S3C6410 = Pull-Both [None,Down,Up,Undef]
* S3C2443 = Pull-Both [not same as S3C6400]
*/
/**
* s3c24xx_gpio_setpull_1up() - Pull configuration for choice of up or none.
* @chip: The gpio chip that is being configured.
* @off: The offset for the GPIO being configured.
* @param: pull: The pull mode being requested.
*
* This is a helper function for the case where we have GPIOs with one
* bit configuring the presence of a pull-up resistor.
*/
extern int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
unsigned int off, samsung_gpio_pull_t pull);
/**
* s3c24xx_gpio_setpull_1down() - Pull configuration for choice of down or none
* @chip: The gpio chip that is being configured
* @off: The offset for the GPIO being configured
* @param: pull: The pull mode being requested
*
* This is a helper function for the case where we have GPIOs with one
* bit configuring the presence of a pull-down resistor.
*/
extern int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
unsigned int off, samsung_gpio_pull_t pull);
/**
* samsung_gpio_setpull_upown() - Pull configuration for choice of up,
* down or none
*
* @chip: The gpio chip that is being configured.
* @off: The offset for the GPIO being configured.
* @param: pull: The pull mode being requested.
*
* This is a helper function for the case where we have GPIOs with two
* bits configuring the presence of a pull resistor, in the following
* order:
* 00 = No pull resistor connected
* 01 = Pull-up resistor connected
* 10 = Pull-down resistor connected
*/
extern int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
unsigned int off, samsung_gpio_pull_t pull);
/**
* samsung_gpio_getpull_updown() - Get configuration for choice of up,
* down or none
*
* @chip: The gpio chip that the GPIO pin belongs to
* @off: The offset to the pin to get the configuration of.
*
* This helper function reads the state of the pull-{up,down} resistor
* for the given GPIO in the same case as samsung_gpio_setpull_upown.
*/
extern samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
unsigned int off);
/**
* s3c24xx_gpio_getpull_1up() - Get configuration for choice of up or none
* @chip: The gpio chip that the GPIO pin belongs to
* @off: The offset to the pin to get the configuration of.
*
* This helper function reads the state of the pull-up resistor for the
* given GPIO in the same case as s3c24xx_gpio_setpull_1up.
*/
extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
unsigned int off);
/**
* s3c24xx_gpio_getpull_1down() - Get configuration for choice of down or none
* @chip: The gpio chip that the GPIO pin belongs to
* @off: The offset to the pin to get the configuration of.
*
* This helper function reads the state of the pull-down resistor for the
* given GPIO in the same case as s3c24xx_gpio_setpull_1down.
*/
extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
unsigned int off);
/**
* s3c2443_gpio_setpull() - Pull configuration for s3c2443.
* @chip: The gpio chip that is being configured.
* @off: The offset for the GPIO being configured.
* @param: pull: The pull mode being requested.
*
* This is a helper function for the case where we have GPIOs with two
* bits configuring the presence of a pull resistor, in the following
* order:
* 00 = Pull-up resistor connected
* 10 = Pull-down resistor connected
* x1 = No pull up resistor
*/
extern int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
unsigned int off, samsung_gpio_pull_t pull);
/**
* s3c2443_gpio_getpull() - Get configuration for s3c2443 pull resistors
* @chip: The gpio chip that the GPIO pin belongs to.
* @off: The offset to the pin to get the configuration of.
*
* This helper function reads the state of the pull-{up,down} resistor for the
* given GPIO in the same case as samsung_gpio_setpull_upown.
*/
extern samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
unsigned int off);
#endif /* __PLAT_GPIO_CFG_HELPERS_H */

View File

@@ -0,0 +1,246 @@
/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg.h
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C Platform - GPIO pin configuration
*
* 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 file contains the necessary definitions to get the basic gpio
* pin configuration done such as setting a pin to input or output or
* changing the pull-{up,down} configurations.
*/
/* Note, this interface is being added to the s3c64xx arch first and will
* be added to the s3c24xx systems later.
*/
#ifndef __PLAT_GPIO_CFG_H
#define __PLAT_GPIO_CFG_H __FILE__
#include <linux/types.h>
typedef unsigned int __bitwise__ samsung_gpio_pull_t;
typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
/* forward declaration if gpio-core.h hasn't been included */
struct samsung_gpio_chip;
/**
* struct samsung_gpio_cfg GPIO configuration
* @cfg_eint: Configuration setting when used for external interrupt source
* @get_pull: Read the current pull configuration for the GPIO
* @set_pull: Set the current pull configuraiton for the GPIO
* @set_config: Set the current configuration for the GPIO
* @get_config: Read the current configuration for the GPIO
*
* Each chip can have more than one type of GPIO bank available and some
* have different capabilites even when they have the same control register
* layouts. Provide an point to vector control routine and provide any
* per-bank configuration information that other systems such as the
* external interrupt code will need.
*
* @sa samsung_gpio_cfgpin
* @sa s3c_gpio_getcfg
* @sa s3c_gpio_setpull
* @sa s3c_gpio_getpull
*/
struct samsung_gpio_cfg {
unsigned int cfg_eint;
samsung_gpio_pull_t (*get_pull)(struct samsung_gpio_chip *chip, unsigned offs);
int (*set_pull)(struct samsung_gpio_chip *chip, unsigned offs,
samsung_gpio_pull_t pull);
unsigned (*get_config)(struct samsung_gpio_chip *chip, unsigned offs);
int (*set_config)(struct samsung_gpio_chip *chip, unsigned offs,
unsigned config);
};
#define S3C_GPIO_SPECIAL_MARK (0xfffffff0)
#define S3C_GPIO_SPECIAL(x) (S3C_GPIO_SPECIAL_MARK | (x))
/* Defines for generic pin configurations */
#define S3C_GPIO_INPUT (S3C_GPIO_SPECIAL(0))
#define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1))
#define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x))
#define samsung_gpio_is_cfg_special(_cfg) \
(((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)
/**
* s3c_gpio_cfgpin() - Change the GPIO function of a pin.
* @pin pin The pin number to configure.
* @to to The configuration for the pin's function.
*
* Configure which function is actually connected to the external
* pin, such as an gpio input, output or some form of special function
* connected to an internal peripheral block.
*
* The @to parameter can be one of the generic S3C_GPIO_INPUT, S3C_GPIO_OUTPUT
* or S3C_GPIO_SFN() to indicate one of the possible values that the helper
* will then generate the correct bit mask and shift for the configuration.
*
* If a bank of GPIOs all needs to be set to special-function 2, then
* the following code will work:
*
* for (gpio = start; gpio < end; gpio++)
* s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
*
* The @to parameter can also be a specific value already shifted to the
* correct position in the control register, although these are discouraged
* in newer kernels and are only being kept for compatibility.
*/
extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);
/**
* s3c_gpio_getcfg - Read the current function for a GPIO pin
* @pin: The pin to read the configuration value for.
*
* Read the configuration state of the given @pin, returning a value that
* could be passed back to s3c_gpio_cfgpin().
*
* @sa s3c_gpio_cfgpin
*/
extern unsigned s3c_gpio_getcfg(unsigned int pin);
/**
* s3c_gpio_cfgpin_range() - Change the GPIO function for configuring pin range
* @start: The pin number to start at
* @nr: The number of pins to configure from @start.
* @cfg: The configuration for the pin's function
*
* Call s3c_gpio_cfgpin() for the @nr pins starting at @start.
*
* @sa s3c_gpio_cfgpin.
*/
extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
unsigned int cfg);
/* Define values for the pull-{up,down} available for each gpio pin.
*
* These values control the state of the weak pull-{up,down} resistors
* available on most pins on the S3C series. Not all chips support both
* up or down settings, and it may be dependent on the chip that is being
* used to whether the particular mode is available.
*/
#define S3C_GPIO_PULL_NONE ((__force samsung_gpio_pull_t)0x00)
#define S3C_GPIO_PULL_DOWN ((__force samsung_gpio_pull_t)0x01)
#define S3C_GPIO_PULL_UP ((__force samsung_gpio_pull_t)0x02)
/**
* s3c_gpio_setpull() - set the state of a gpio pin pull resistor
* @pin: The pin number to configure the pull resistor.
* @pull: The configuration for the pull resistor.
*
* This function sets the state of the pull-{up,down} resistor for the
* specified pin. It will return 0 if successful, or a negative error
* code if the pin cannot support the requested pull setting.
*
* @pull is one of S3C_GPIO_PULL_NONE, S3C_GPIO_PULL_DOWN or S3C_GPIO_PULL_UP.
*/
extern int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull);
/**
* s3c_gpio_getpull() - get the pull resistor state of a gpio pin
* @pin: The pin number to get the settings for
*
* Read the pull resistor value for the specified pin.
*/
extern samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
/* configure `all` aspects of an gpio */
/**
* s3c_gpio_cfgall_range() - configure range of gpio functtion and pull.
* @start: The gpio number to start at.
* @nr: The number of gpio to configure from @start.
* @cfg: The configuration to use
* @pull: The pull setting to use.
*
* Run s3c_gpio_cfgpin() and s3c_gpio_setpull() over the gpio range starting
* @gpio and running for @size.
*
* @sa s3c_gpio_cfgpin
* @sa s3c_gpio_setpull
* @sa s3c_gpio_cfgpin_range
*/
extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
unsigned int cfg, samsung_gpio_pull_t pull);
static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size,
unsigned int cfg)
{
return s3c_gpio_cfgall_range(pin, size, cfg, S3C_GPIO_PULL_NONE);
}
/* Define values for the drvstr available for each gpio pin.
*
* These values control the value of the output signal driver strength,
* configurable on most pins on the S5P series.
*/
#define S5P_GPIO_DRVSTR_LV1 ((__force s5p_gpio_drvstr_t)0x0)
#define S5P_GPIO_DRVSTR_LV2 ((__force s5p_gpio_drvstr_t)0x2)
#define S5P_GPIO_DRVSTR_LV3 ((__force s5p_gpio_drvstr_t)0x1)
#define S5P_GPIO_DRVSTR_LV4 ((__force s5p_gpio_drvstr_t)0x3)
/**
* s5c_gpio_get_drvstr() - get the driver streght value of a gpio pin
* @pin: The pin number to get the settings for
*
* Read the driver streght value for the specified pin.
*/
extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin);
/**
* s3c_gpio_set_drvstr() - set the driver streght value of a gpio pin
* @pin: The pin number to configure the driver streght value
* @drvstr: The new value of the driver strength
*
* This function sets the driver strength value for the specified pin.
* It will return 0 if successful, or a negative error code if the pin
* cannot support the requested setting.
*/
extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr);
/**
* s5p_register_gpio_interrupt() - register interrupt support for a gpio group
* @pin: The pin number from the group to be registered
*
* This function registers gpio interrupt support for the group that the
* specified pin belongs to.
*
* The total number of gpio pins is quite large ob s5p series. Registering
* irq support for all of them would be a resource waste. Because of that the
* interrupt support for standard gpio pins is registered dynamically.
*
* It will return the irq number of the interrupt that has been registered
* or -ENOMEM if no more gpio interrupts can be registered. It is allowed
* to call this function more than once for the same gpio group (the group
* will be registered only once).
*/
extern int s5p_register_gpio_interrupt(int pin);
/** s5p_register_gpioint_bank() - add gpio bank for further gpio interrupt
* registration (see s5p_register_gpio_interrupt function)
* @chain_irq: chained irq number for the gpio int handler for this bank
* @start: start gpio group number of this bank
* @nr_groups: number of gpio groups handled by this bank
*
* This functions registers initial information about gpio banks that
* can be later used by the s5p_register_gpio_interrupt() function to
* enable support for gpio interrupt for particular gpio group.
*/
#ifdef CONFIG_S5P_GPIO_INT
extern int s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups);
#else
#define s5p_register_gpioint_bank(chain_irq, start, nr_groups) do { } while (0)
#endif
#endif /* __PLAT_GPIO_CFG_H */

View File

@@ -0,0 +1,142 @@
/* linux/arch/arm/plat-s3c/include/plat/gpio-core.h
*
* Copyright 2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C Platform - GPIO core
*
* 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.
*/
#ifndef __PLAT_SAMSUNG_GPIO_CORE_H
#define __PLAT_SAMSUNG_GPIO_CORE_H
#define GPIOCON_OFF (0x00)
#define GPIODAT_OFF (0x04)
#define con_4bit_shift(__off) ((__off) * 4)
/* Define the core gpiolib support functions that the s3c platforms may
* need to extend or change depending on the hardware and the s3c chip
* selected at build or found at run time.
*
* These definitions are not intended for driver inclusion, there is
* nothing here that should not live outside the platform and core
* specific code.
*/
struct samsung_gpio_chip;
/**
* struct samsung_gpio_pm - power management (suspend/resume) information
* @save: Routine to save the state of the GPIO block
* @resume: Routine to resume the GPIO block.
*/
struct samsung_gpio_pm {
void (*save)(struct samsung_gpio_chip *chip);
void (*resume)(struct samsung_gpio_chip *chip);
};
struct samsung_gpio_cfg;
/**
* struct samsung_gpio_chip - wrapper for specific implementation of gpio
* @chip: The chip structure to be exported via gpiolib.
* @base: The base pointer to the gpio configuration registers.
* @group: The group register number for gpio interrupt support.
* @irq_base: The base irq number.
* @config: special function and pull-resistor control information.
* @lock: Lock for exclusive access to this gpio bank.
* @pm_save: Save information for suspend/resume support.
* @bitmap_gpio_int: Bitmap for representing GPIO interrupt or not.
*
* This wrapper provides the necessary information for the Samsung
* specific gpios being registered with gpiolib.
*
* The lock protects each gpio bank from multiple access of the shared
* configuration registers, or from reading of data whilst another thread
* is writing to the register set.
*
* Each chip has its own lock to avoid any contention between different
* CPU cores trying to get one lock for different GPIO banks, where each
* bank of GPIO has its own register space and configuration registers.
*/
struct samsung_gpio_chip {
struct gpio_chip chip;
struct samsung_gpio_cfg *config;
struct samsung_gpio_pm *pm;
void __iomem *base;
int irq_base;
int group;
spinlock_t lock;
#ifdef CONFIG_PM
u32 pm_save[4];
#endif
u32 bitmap_gpio_int;
};
static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc)
{
return container_of(gpc, struct samsung_gpio_chip, chip);
}
/**
* samsung_gpiolib_to_irq - convert gpio pin to irq number
* @chip: The gpio chip that the pin belongs to.
* @offset: The offset of the pin in the chip.
*
* This helper returns the irq number calculated from the chip->irq_base and
* the provided offset.
*/
extern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset);
/* exported for core SoC support to change */
extern struct samsung_gpio_cfg s3c24xx_gpiocfg_default;
#ifdef CONFIG_S3C_GPIO_TRACK
extern struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int chip)
{
return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL;
}
#else
/* machine specific code should provide samsung_gpiolib_getchip */
extern struct samsung_gpio_chip s3c24xx_gpios[];
static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int pin)
{
struct samsung_gpio_chip *chip;
if (pin > S3C_GPIO_END)
return NULL;
chip = &s3c24xx_gpios[pin/32];
return ((pin - chip->chip.base) < chip->chip.ngpio) ? chip : NULL;
}
static inline void s3c_gpiolib_track(struct samsung_gpio_chip *chip) { }
#endif
#ifdef CONFIG_PM
extern struct samsung_gpio_pm samsung_gpio_pm_1bit;
extern struct samsung_gpio_pm samsung_gpio_pm_2bit;
extern struct samsung_gpio_pm samsung_gpio_pm_4bit;
#define __gpio_pm(x) x
#else
#define samsung_gpio_pm_1bit NULL
#define samsung_gpio_pm_2bit NULL
#define samsung_gpio_pm_4bit NULL
#define __gpio_pm(x) NULL
#endif /* CONFIG_PM */
/* locking wrappers to deal with multiple access to the same gpio bank */
#define samsung_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
#define samsung_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
#endif /* __PLAT_SAMSUNG_GPIO_CORE_H */

View File

@@ -0,0 +1,16 @@
/*
* Copyright (C) 2012 Samsung Electronics Co.Ltd
*
* 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.
*/
#ifndef __PLAT_SAMSUNG_HDMI_H
#define __PLAT_SAMSUNG_HDMI_H __FILE__
extern void s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
struct i2c_board_info *mhl_info, int mhl_bus);
#endif /* __PLAT_SAMSUNG_HDMI_H */

View File

@@ -0,0 +1,42 @@
/* arch/arm/mach-s3c2410/include/mach/iic-core.h
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C - I2C Controller core functions
*
* 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.
*/
#ifndef __ASM_ARCH_IIC_CORE_H
#define __ASM_ARCH_IIC_CORE_H __FILE__
/* These functions are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void s3c_i2c0_setname(char *name)
{
/* currently this device is always compiled in */
s3c_device_i2c0.name = name;
}
static inline void s3c_i2c1_setname(char *name)
{
#ifdef CONFIG_S3C_DEV_I2C1
s3c_device_i2c1.name = name;
#endif
}
static inline void s3c_i2c2_setname(char *name)
{
#ifdef CONFIG_S3C_DEV_I2C2
s3c_device_i2c2.name = name;
#endif
}
#endif /* __ASM_ARCH_IIC_H */

View File

@@ -0,0 +1,20 @@
/* arch/arm/plat-samsung/include/plat/irq-uart.h
*
* Copyright (c) 2010 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Header file for Samsung SoC UART IRQ demux for S3C64XX and later
*
* 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.
*/
struct s3c_uart_irq {
void __iomem *regs;
unsigned int base_irq;
unsigned int parent_irq;
};
extern void s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs);

View File

@@ -0,0 +1,13 @@
/* arch/arm/plat-samsung/include/plat/irq-vic-timer.h
*
* Copyright (c) 2010 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Header file for Samsung SoC IRQ VIC timer
*
* 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.
*/
extern void s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq);

View File

@@ -0,0 +1,81 @@
/* linux/arch/arm/plat-samsung/include/plat/irqs.h
*
* Copyright (c) 2009 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S5P Common IRQ support
*
* 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.
*/
#ifndef __PLAT_SAMSUNG_IRQS_H
#define __PLAT_SAMSUNG_IRQS_H __FILE__
/* we keep the first set of CPU IRQs out of the range of
* the ISA space, so that the PC104 has them to itself
* and we don't end up having to do horrible things to the
* standard ISA drivers....
*
* note, since we're using the VICs, our start must be a
* mulitple of 32 to allow the common code to work
*/
#define S5P_IRQ_OFFSET (32)
#define S5P_IRQ(x) ((x) + S5P_IRQ_OFFSET)
#define S5P_VIC0_BASE S5P_IRQ(0)
#define S5P_VIC1_BASE S5P_IRQ(32)
#define S5P_VIC2_BASE S5P_IRQ(64)
#define S5P_VIC3_BASE S5P_IRQ(96)
#define VIC_BASE(x) (S5P_VIC0_BASE + ((x)*32))
#define IRQ_VIC0_BASE S5P_VIC0_BASE
#define IRQ_VIC1_BASE S5P_VIC1_BASE
#define IRQ_VIC2_BASE S5P_VIC2_BASE
/* VIC based IRQs */
#define S5P_IRQ_VIC0(x) (S5P_VIC0_BASE + (x))
#define S5P_IRQ_VIC1(x) (S5P_VIC1_BASE + (x))
#define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x))
#define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x))
#define S5P_TIMER_IRQ(x) (IRQ_TIMER_BASE + (x))
#define IRQ_TIMER0 S5P_TIMER_IRQ(0)
#define IRQ_TIMER1 S5P_TIMER_IRQ(1)
#define IRQ_TIMER2 S5P_TIMER_IRQ(2)
#define IRQ_TIMER3 S5P_TIMER_IRQ(3)
#define IRQ_TIMER4 S5P_TIMER_IRQ(4)
#define IRQ_TIMER_COUNT (5)
#define IRQ_EINT(x) ((x) < 16 ? ((x) + S5P_EINT_BASE1) \
: ((x) - 16 + S5P_EINT_BASE2))
#define EINT_OFFSET(irq) ((irq) < S5P_EINT_BASE2 ? \
((irq) - S5P_EINT_BASE1) : \
((irq) + 16 - S5P_EINT_BASE2))
#define IRQ_EINT_BIT(x) EINT_OFFSET(x)
/* Typically only a few gpio chips require gpio interrupt support.
To avoid memory waste irq descriptors are allocated only for
S5P_GPIOINT_GROUP_COUNT chips, each with total number of
S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged
to any gpio chip with the s5p_register_gpio_interrupt() function */
#define S5P_GPIOINT_GROUP_COUNT 4
#define S5P_GPIOINT_GROUP_SIZE 8
#define S5P_GPIOINT_COUNT (S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE)
/* IRQ types common for all s5p platforms */
#define S5P_IRQ_TYPE_LEVEL_LOW (0x00)
#define S5P_IRQ_TYPE_LEVEL_HIGH (0x01)
#define S5P_IRQ_TYPE_EDGE_FALLING (0x02)
#define S5P_IRQ_TYPE_EDGE_RISING (0x03)
#define S5P_IRQ_TYPE_EDGE_BOTH (0x04)
#endif /* __PLAT_SAMSUNG_IRQS_H */

View File

@@ -0,0 +1,31 @@
/*
* linux/arch/arm/plat-samsung/include/plat/keypad-core.h
*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* Samsung keypad controller core function
*
* 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.
*
*/
#ifndef __ASM_ARCH_KEYPAD_CORE_H
#define __ASM_ARCH_KEYPAD_CORE_H
/* These function are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void samsung_keypad_setname(char *name)
{
#ifdef CONFIG_SAMSUNG_DEV_KEYPAD
samsung_device_keypad.name = name;
#endif
}
#endif /* __ASM_ARCH_KEYPAD_CORE_H */

View File

@@ -0,0 +1,31 @@
/*
* Samsung Platform - Keypad platform data definitions
*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* 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.
*/
#ifndef __PLAT_SAMSUNG_KEYPAD_H
#define __PLAT_SAMSUNG_KEYPAD_H
#include <linux/input/samsung-keypad.h>
/**
* samsung_keypad_set_platdata - Set platform data for Samsung Keypad device.
* @pd: Platform data to register to device.
*
* Register the given platform data for use with Samsung Keypad device.
* The call will copy the platform data, so the board definitions can
* make the structure itself __initdata.
*/
extern void samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd);
/* defined by architecture to configure gpio. */
extern void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols);
#endif /* __PLAT_SAMSUNG_KEYPAD_H */

View File

@@ -0,0 +1,46 @@
/* linux/include/asm-arm/plat-s3c/map.h
*
* Copyright 2003, 2007 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C - Memory map definitions (virtual addresses)
*
* 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.
*/
#ifndef __ASM_PLAT_MAP_H
#define __ASM_PLAT_MAP_H __FILE__
/* Fit all our registers in at 0xF6000000 upwards, trying to use as
* little of the VA space as possible so vmalloc and friends have a
* better chance of getting memory.
*
* we try to ensure stuff like the IRQ registers are available for
* an single MOVS instruction (ie, only 8 bits of set data)
*/
#define S3C_ADDR_BASE 0xF6000000
#ifndef __ASSEMBLY__
#define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x))
#else
#define S3C_ADDR(x) (S3C_ADDR_BASE + (x))
#endif
#define S3C_VA_IRQ S3C_ADDR(0x00000000) /* irq controller(s) */
#define S3C_VA_SYS S3C_ADDR(0x00100000) /* system control */
#define S3C_VA_MEM S3C_ADDR(0x00200000) /* memory control */
#define S3C_VA_TIMER S3C_ADDR(0x00300000) /* timer block */
#define S3C_VA_WATCHDOG S3C_ADDR(0x00400000) /* watchdog */
#define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */
/* This is used for the CPU specific mappings that may be needed, so that
* they do not need to directly used S3C_ADDR() and thus make it easier to
* modify the space for mapping.
*/
#define S3C_ADDR_CPU(x) S3C_ADDR(0x00500000 + (x))
#endif /* __ASM_PLAT_MAP_H */

View File

@@ -0,0 +1,84 @@
/* linux/arch/arm/plat-samsung/include/plat/map-s3c.h
*
* Copyright (c) 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C24XX - Memory map definitions
*
* 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.
*/
#ifndef __ASM_PLAT_MAP_S3C_H
#define __ASM_PLAT_MAP_S3C_H __FILE__
#define S3C24XX_VA_IRQ S3C_VA_IRQ
#define S3C24XX_VA_MEMCTRL S3C_VA_MEM
#define S3C24XX_VA_UART S3C_VA_UART
#define S3C24XX_VA_TIMER S3C_VA_TIMER
#define S3C24XX_VA_CLKPWR S3C_VA_SYS
#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG
#define S3C2412_VA_SSMC S3C_ADDR_CPU(0x00000000)
#define S3C2412_VA_EBI S3C_ADDR_CPU(0x00100000)
#define S3C2410_PA_UART (0x50000000)
#define S3C24XX_PA_UART S3C2410_PA_UART
#ifndef S3C_UART_OFFSET
#define S3C_UART_OFFSET (0x400)
#endif
/*
* GPIO ports
*
* the calculation for the VA of this must ensure that
* it is the same distance apart from the UART in the
* phsyical address space, as the initial mapping for the IO
* is done as a 1:1 mapping. This puts it (currently) at
* 0xFA800000, which is not in the way of any current mapping
* by the base system.
*/
#define S3C2410_PA_GPIO (0x56000000)
#define S3C24XX_PA_GPIO S3C2410_PA_GPIO
#define S3C24XX_VA_GPIO ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
#define S3C64XX_VA_GPIO S3C_ADDR_CPU(0x00000000)
#define S3C64XX_VA_MODEM S3C_ADDR_CPU(0x00100000)
#define S3C64XX_VA_USB_HSPHY S3C_ADDR_CPU(0x00200000)
#define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY
/*
* ISA style IO, for each machine to sort out mappings for,
* if it implements it. We reserve two 16M regions for ISA.
*/
#define S3C2410_ADDR(x) S3C_ADDR(x)
#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000)
#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000)
/* deal with the registers that move under the 2412/2413 */
#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
#ifndef __ASSEMBLY__
extern void __iomem *s3c24xx_va_gpio2;
#endif
#ifdef CONFIG_CPU_S3C2412_ONLY
#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10)
#else
#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
#endif
#else
#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
#endif
#include <plat/map-s5p.h>
#endif /* __ASM_PLAT_MAP_S3C_H */

View File

@@ -0,0 +1,62 @@
/* linux/arch/arm/plat-samsung/include/plat/map-s5p.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S5P - Memory map definitions
*
* 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.
*/
#ifndef __ASM_PLAT_MAP_S5P_H
#define __ASM_PLAT_MAP_S5P_H __FILE__
#define S5P_VA_CHIPID S3C_ADDR(0x02000000)
#define S5P_VA_CMU S3C_ADDR(0x02100000)
#define S5P_VA_PMU S3C_ADDR(0x02180000)
#define S5P_VA_GPIO S3C_ADDR(0x02200000)
#define S5P_VA_GPIO1 S5P_VA_GPIO
#define S5P_VA_GPIO2 S3C_ADDR(0x02240000)
#define S5P_VA_GPIO3 S3C_ADDR(0x02280000)
#define S5P_VA_SYSRAM S3C_ADDR(0x02400000)
#define S5P_VA_SYSRAM_NS S3C_ADDR(0x02410000)
#define S5P_VA_DMC0 S3C_ADDR(0x02440000)
#define S5P_VA_DMC1 S3C_ADDR(0x02480000)
#define S5P_VA_SROMC S3C_ADDR(0x024C0000)
#define S5P_VA_SYSTIMER S3C_ADDR(0x02500000)
#define S5P_VA_L2CC S3C_ADDR(0x02600000)
#define S5P_VA_COMBINER_BASE S3C_ADDR(0x02700000)
#define S5P_VA_COMBINER(x) (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
#define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000)
#define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x))
#define S5P_VA_SCU S5P_VA_COREPERI(0x0)
#define S5P_VA_TWD S5P_VA_COREPERI(0x600)
#define S5P_VA_GIC_CPU S3C_ADDR(0x02810000)
#define S5P_VA_GIC_DIST S3C_ADDR(0x02820000)
#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
#define VA_VIC0 VA_VIC(0)
#define VA_VIC1 VA_VIC(1)
#define VA_VIC2 VA_VIC(2)
#define VA_VIC3 VA_VIC(3)
#define S5P_VA_UART(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
#define S5P_VA_UART0 S5P_VA_UART(0)
#define S5P_VA_UART1 S5P_VA_UART(1)
#define S5P_VA_UART2 S5P_VA_UART(2)
#define S5P_VA_UART3 S5P_VA_UART(3)
#ifndef S3C_UART_OFFSET
#define S3C_UART_OFFSET (0x400)
#endif
#include <plat/map-s3c.h>
#endif /* __ASM_PLAT_MAP_S5P_H */

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2011 Samsung Electronics Co.Ltd
*
* 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.
*/
#ifndef __PLAT_SAMSUNG_MFC_H
#define __PLAT_SAMSUNG_MFC_H __FILE__
struct s5p_mfc_dt_meminfo {
unsigned long loff;
unsigned long lsize;
unsigned long roff;
unsigned long rsize;
char *compatible;
};
/**
* s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
* @rbase: base address for MFC 'right' memory interface
* @rsize: size of the memory reserved for MFC 'right' interface
* @lbase: base address for MFC 'left' memory interface
* @lsize: size of the memory reserved for MFC 'left' interface
*
* This function reserves system memory for both MFC device memory
* interfaces and registers it to respective struct device entries as
* coherent memory.
*/
void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
phys_addr_t lbase, unsigned int lsize);
int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname,
int depth, void *data);
#endif /* __PLAT_SAMSUNG_MFC_H */

View File

@@ -0,0 +1,28 @@
/* arch/arm/plat-samsung/include/plat/nand-core.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S3C - Nand Controller core functions
*
* 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.
*/
#ifndef __ASM_ARCH_NAND_CORE_H
#define __ASM_ARCH_NAND_CORE_H __FILE__
/* These functions are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void s3c_nand_setname(char *name)
{
#ifdef CONFIG_S3C_DEV_NAND
s3c_device_nand.name = name;
#endif
}
#endif /* __ASM_ARCH_NAND_CORE_H */

View File

@@ -0,0 +1,37 @@
/*
* linux/arch/arm/plat-samsung/onenand-core.h
*
* Copyright (c) 2010 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
* Marek Szyprowski <m.szyprowski@samsung.com>
*
* Samsung OneNAD Controller core functions
*
* 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.
*/
#ifndef __ASM_ARCH_ONENAND_CORE_H
#define __ASM_ARCH_ONENAND_CORE_H __FILE__
/* These functions are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void s3c_onenand_setname(char *name)
{
#ifdef CONFIG_S3C_DEV_ONENAND
s3c_device_onenand.name = name;
#endif
}
static inline void s3c64xx_onenand1_setname(char *name)
{
#ifdef CONFIG_S3C64XX_DEV_ONENAND1
s3c64xx_device_onenand1.name = name;
#endif
}
#endif /* __ASM_ARCH_ONENAND_CORE_H */

View File

@@ -0,0 +1,323 @@
/* linux/arch/arm/plat-samsung/include/plat/pll.h
*
* Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* Samsung PLL codes
*
* 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/div64.h>
#define S3C24XX_PLL_MDIV_MASK (0xFF)
#define S3C24XX_PLL_PDIV_MASK (0x1F)
#define S3C24XX_PLL_SDIV_MASK (0x3)
#define S3C24XX_PLL_MDIV_SHIFT (12)
#define S3C24XX_PLL_PDIV_SHIFT (4)
#define S3C24XX_PLL_SDIV_SHIFT (0)
static inline unsigned int s3c24xx_get_pll(unsigned int pllval,
unsigned int baseclk)
{
unsigned int mdiv, pdiv, sdiv;
uint64_t fvco;
mdiv = (pllval >> S3C24XX_PLL_MDIV_SHIFT) & S3C24XX_PLL_MDIV_MASK;
pdiv = (pllval >> S3C24XX_PLL_PDIV_SHIFT) & S3C24XX_PLL_PDIV_MASK;
sdiv = (pllval >> S3C24XX_PLL_SDIV_SHIFT) & S3C24XX_PLL_SDIV_MASK;
fvco = (uint64_t)baseclk * (mdiv + 8);
do_div(fvco, (pdiv + 2) << sdiv);
return (unsigned int)fvco;
}
#define S3C2416_PLL_MDIV_MASK (0x3FF)
#define S3C2416_PLL_PDIV_MASK (0x3F)
#define S3C2416_PLL_SDIV_MASK (0x7)
#define S3C2416_PLL_MDIV_SHIFT (14)
#define S3C2416_PLL_PDIV_SHIFT (5)
#define S3C2416_PLL_SDIV_SHIFT (0)
static inline unsigned int s3c2416_get_pll(unsigned int pllval,
unsigned int baseclk)
{
unsigned int mdiv, pdiv, sdiv;
uint64_t fvco;
mdiv = (pllval >> S3C2416_PLL_MDIV_SHIFT) & S3C2416_PLL_MDIV_MASK;
pdiv = (pllval >> S3C2416_PLL_PDIV_SHIFT) & S3C2416_PLL_PDIV_MASK;
sdiv = (pllval >> S3C2416_PLL_SDIV_SHIFT) & S3C2416_PLL_SDIV_MASK;
fvco = (uint64_t)baseclk * mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned int)fvco;
}
#define S3C6400_PLL_MDIV_MASK (0x3FF)
#define S3C6400_PLL_PDIV_MASK (0x3F)
#define S3C6400_PLL_SDIV_MASK (0x7)
#define S3C6400_PLL_MDIV_SHIFT (16)
#define S3C6400_PLL_PDIV_SHIFT (8)
#define S3C6400_PLL_SDIV_SHIFT (0)
static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
u32 pllcon)
{
u32 mdiv, pdiv, sdiv;
u64 fvco = baseclk;
mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
fvco *= mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned long)fvco;
}
#define PLL6553X_MDIV_MASK (0x7F)
#define PLL6553X_PDIV_MASK (0x1F)
#define PLL6553X_SDIV_MASK (0x3)
#define PLL6553X_KDIV_MASK (0xFFFF)
#define PLL6553X_MDIV_SHIFT (16)
#define PLL6553X_PDIV_SHIFT (8)
#define PLL6553X_SDIV_SHIFT (0)
static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
u32 pll_con0, u32 pll_con1)
{
unsigned long result;
u32 mdiv, pdiv, sdiv, kdiv;
u64 tmp;
mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
kdiv = pll_con1 & PLL6553X_KDIV_MASK;
/*
* We need to multiple baseclk by mdiv (the integer part) and kdiv
* which is in 2^16ths, so shift mdiv up (does not overflow) and
* add kdiv before multiplying. The use of tmp is to avoid any
* overflows before shifting bac down into result when multipling
* by the mdiv and kdiv pair.
*/
tmp = baseclk;
tmp *= (mdiv << 16) + kdiv;
do_div(tmp, (pdiv << sdiv));
result = tmp >> 16;
return result;
}
#define PLL35XX_MDIV_MASK (0x3FF)
#define PLL35XX_PDIV_MASK (0x3F)
#define PLL35XX_SDIV_MASK (0x7)
#define PLL35XX_MDIV_SHIFT (16)
#define PLL35XX_PDIV_SHIFT (8)
#define PLL35XX_SDIV_SHIFT (0)
static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
{
u32 mdiv, pdiv, sdiv;
u64 fvco = baseclk;
mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
fvco *= mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned long)fvco;
}
#define PLL36XX_KDIV_MASK (0xFFFF)
#define PLL36XX_MDIV_MASK (0x1FF)
#define PLL36XX_PDIV_MASK (0x3F)
#define PLL36XX_SDIV_MASK (0x7)
#define PLL36XX_MDIV_SHIFT (16)
#define PLL36XX_PDIV_SHIFT (8)
#define PLL36XX_SDIV_SHIFT (0)
static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
u32 pll_con0, u32 pll_con1)
{
unsigned long result;
u32 mdiv, pdiv, sdiv, kdiv;
u64 tmp;
mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
kdiv = pll_con1 & PLL36XX_KDIV_MASK;
tmp = baseclk;
tmp *= (mdiv << 16) + kdiv;
do_div(tmp, (pdiv << sdiv));
result = tmp >> 16;
return result;
}
#define PLL45XX_MDIV_MASK (0x3FF)
#define PLL45XX_PDIV_MASK (0x3F)
#define PLL45XX_SDIV_MASK (0x7)
#define PLL45XX_MDIV_SHIFT (16)
#define PLL45XX_PDIV_SHIFT (8)
#define PLL45XX_SDIV_SHIFT (0)
enum pll45xx_type_t {
pll_4500,
pll_4502,
pll_4508
};
static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
enum pll45xx_type_t pll_type)
{
u32 mdiv, pdiv, sdiv;
u64 fvco = baseclk;
mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
if (pll_type == pll_4508)
sdiv = sdiv - 1;
fvco *= mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned long)fvco;
}
/* CON0 bit-fields */
#define PLL46XX_MDIV_MASK (0x1FF)
#define PLL46XX_PDIV_MASK (0x3F)
#define PLL46XX_SDIV_MASK (0x7)
#define PLL46XX_LOCKED_SHIFT (29)
#define PLL46XX_MDIV_SHIFT (16)
#define PLL46XX_PDIV_SHIFT (8)
#define PLL46XX_SDIV_SHIFT (0)
/* CON1 bit-fields */
#define PLL46XX_MRR_MASK (0x1F)
#define PLL46XX_MFR_MASK (0x3F)
#define PLL46XX_KDIV_MASK (0xFFFF)
#define PLL4650C_KDIV_MASK (0xFFF)
#define PLL46XX_MRR_SHIFT (24)
#define PLL46XX_MFR_SHIFT (16)
#define PLL46XX_KDIV_SHIFT (0)
enum pll46xx_type_t {
pll_4600,
pll_4650,
pll_4650c,
};
static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
u32 pll_con0, u32 pll_con1,
enum pll46xx_type_t pll_type)
{
unsigned long result;
u32 mdiv, pdiv, sdiv, kdiv;
u64 tmp;
mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
kdiv = pll_con1 & PLL46XX_KDIV_MASK;
if (pll_type == pll_4650c)
kdiv = pll_con1 & PLL4650C_KDIV_MASK;
else
kdiv = pll_con1 & PLL46XX_KDIV_MASK;
tmp = baseclk;
if (pll_type == pll_4600) {
tmp *= (mdiv << 16) + kdiv;
do_div(tmp, (pdiv << sdiv));
result = tmp >> 16;
} else {
tmp *= (mdiv << 10) + kdiv;
do_div(tmp, (pdiv << sdiv));
result = tmp >> 10;
}
return result;
}
#define PLL90XX_MDIV_MASK (0xFF)
#define PLL90XX_PDIV_MASK (0x3F)
#define PLL90XX_SDIV_MASK (0x7)
#define PLL90XX_KDIV_MASK (0xffff)
#define PLL90XX_LOCKED_SHIFT (29)
#define PLL90XX_MDIV_SHIFT (16)
#define PLL90XX_PDIV_SHIFT (8)
#define PLL90XX_SDIV_SHIFT (0)
#define PLL90XX_KDIV_SHIFT (0)
static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
u32 pll_con, u32 pll_conk)
{
unsigned long result;
u32 mdiv, pdiv, sdiv, kdiv;
u64 tmp;
mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
kdiv = pll_conk & PLL90XX_KDIV_MASK;
/*
* We need to multiple baseclk by mdiv (the integer part) and kdiv
* which is in 2^16ths, so shift mdiv up (does not overflow) and
* add kdiv before multiplying. The use of tmp is to avoid any
* overflows before shifting bac down into result when multipling
* by the mdiv and kdiv pair.
*/
tmp = baseclk;
tmp *= (mdiv << 16) + kdiv;
do_div(tmp, (pdiv << sdiv));
result = tmp >> 16;
return result;
}
#define PLL65XX_MDIV_MASK (0x3FF)
#define PLL65XX_PDIV_MASK (0x3F)
#define PLL65XX_SDIV_MASK (0x7)
#define PLL65XX_MDIV_SHIFT (16)
#define PLL65XX_PDIV_SHIFT (8)
#define PLL65XX_SDIV_SHIFT (0)
static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
{
u32 mdiv, pdiv, sdiv;
u64 fvco = baseclk;
mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
fvco *= mdiv;
do_div(fvco, (pdiv << sdiv));
return (unsigned long)fvco;
}

View File

@@ -0,0 +1,186 @@
/* arch/arm/plat-samsung/include/plat/pm.h
*
* Copyright (c) 2004 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Written by Ben Dooks, <ben@simtec.co.uk>
*
* 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.
*/
/* s3c_pm_init
*
* called from board at initialisation time to setup the power
* management
*/
#include <linux/irq.h>
struct device;
#ifdef CONFIG_PM
extern __init int s3c_pm_init(void);
extern __init int s3c64xx_pm_init(void);
#else
static inline int s3c_pm_init(void)
{
return 0;
}
static inline int s3c64xx_pm_init(void)
{
return 0;
}
#endif
/* configuration for the IRQ mask over sleep */
extern unsigned long s3c_irqwake_intmask;
extern unsigned long s3c_irqwake_eintmask;
/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
extern unsigned long s3c_irqwake_intallow;
extern unsigned long s3c_irqwake_eintallow;
/* per-cpu sleep functions */
extern void (*pm_cpu_prep)(void);
extern int (*pm_cpu_sleep)(unsigned long);
/* Flags for PM Control */
extern unsigned long s3c_pm_flags;
extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */
/* from sleep.S */
extern void s3c_cpu_resume(void);
extern int s3c2410_cpu_suspend(unsigned long);
/* sleep save info */
/**
* struct sleep_save - save information for shared peripherals.
* @reg: Pointer to the register to save.
* @val: Holder for the value saved from reg.
*
* This describes a list of registers which is used by the pm core and
* other subsystem to save and restore register values over suspend.
*/
struct sleep_save {
void __iomem *reg;
unsigned long val;
};
#define SAVE_ITEM(x) \
{ .reg = (x) }
/**
* struct pm_uart_save - save block for core UART
* @ulcon: Save value for S3C2410_ULCON
* @ucon: Save value for S3C2410_UCON
* @ufcon: Save value for S3C2410_UFCON
* @umcon: Save value for S3C2410_UMCON
* @ubrdiv: Save value for S3C2410_UBRDIV
*
* Save block for UART registers to be held over sleep and restored if they
* are needed (say by debug).
*/
struct pm_uart_save {
u32 ulcon;
u32 ucon;
u32 ufcon;
u32 umcon;
u32 ubrdiv;
u32 udivslot;
};
/* helper functions to save/restore lists of registers. */
extern void s3c_pm_do_save(struct sleep_save *ptr, int count);
extern void s3c_pm_do_restore(struct sleep_save *ptr, int count);
extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
#ifdef CONFIG_PM
extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
#else
#define s3c_irq_wake NULL
#define s3c_irqext_wake NULL
#endif
/* PM debug functions */
#ifdef CONFIG_SAMSUNG_PM_DEBUG
/**
* s3c_pm_dbg() - low level debug function for use in suspend/resume.
* @msg: The message to print.
*
* This function is used mainly to debug the resume process before the system
* can rely on printk/console output. It uses the low-level debugging output
* routine printascii() to do its work.
*/
extern void s3c_pm_dbg(const char *msg, ...);
#define S3C_PMDBG(fmt...) s3c_pm_dbg(fmt)
#else
#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
#endif
#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
/**
* s3c_pm_debug_smdkled() - Debug PM suspend/resume via SMDK Board LEDs
* @set: set bits for the state of the LEDs
* @clear: clear bits for the state of the LEDs.
*/
extern void s3c_pm_debug_smdkled(u32 set, u32 clear);
#else
static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { }
#endif /* CONFIG_S3C_PM_DEBUG_LED_SMDK */
/* suspend memory checking */
#ifdef CONFIG_SAMSUNG_PM_CHECK
extern void s3c_pm_check_prepare(void);
extern void s3c_pm_check_restore(void);
extern void s3c_pm_check_cleanup(void);
extern void s3c_pm_check_store(void);
#else
#define s3c_pm_check_prepare() do { } while(0)
#define s3c_pm_check_restore() do { } while(0)
#define s3c_pm_check_cleanup() do { } while(0)
#define s3c_pm_check_store() do { } while(0)
#endif
/**
* s3c_pm_configure_extint() - ensure pins are correctly set for IRQ
*
* Setup all the necessary GPIO pins for waking the system on external
* interrupt.
*/
extern void s3c_pm_configure_extint(void);
/**
* samsung_pm_restore_gpios() - restore the state of the gpios after sleep.
*
* Restore the state of the GPIO pins after sleep, which may involve ensuring
* that we do not glitch the state of the pins from that the bootloader's
* resume code has done.
*/
extern void samsung_pm_restore_gpios(void);
/**
* samsung_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
*
* Save the GPIO states for resotration on resume. See samsung_pm_restore_gpios().
*/
extern void samsung_pm_save_gpios(void);
extern void s3c_pm_save_core(void);
extern void s3c_pm_restore_core(void);

View File

@@ -0,0 +1,81 @@
/* linux/arch/arm/plat-samsung/include/plat/pwm-clock.h
*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* SAMSUNG - pwm clock and timer support
*
* 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.
*/
#ifndef __ASM_PLAT_PWM_CLOCK_H
#define __ASM_PLAT_PWM_CLOCK_H __FILE__
/**
* pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
* @tcfg: The timer TCFG1 register bits shifted down to 0.
*
* Return true if the given configuration from TCFG1 is a TCLK instead
* any of the TDIV clocks.
*/
static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
{
if (soc_is_s3c24xx())
return tcfg == S3C2410_TCFG1_MUX_TCLK;
else if (soc_is_s3c64xx() || soc_is_s5pc100())
return tcfg >= S3C64XX_TCFG1_MUX_TCLK;
else if (soc_is_s5p6440() || soc_is_s5p6450())
return 0;
else
return tcfg == S3C64XX_TCFG1_MUX_TCLK;
}
/**
* tcfg_to_divisor() - convert tcfg1 setting to a divisor
* @tcfg1: The tcfg1 setting, shifted down.
*
* Get the divisor value for the given tcfg1 setting. We assume the
* caller has already checked to see if this is not a TCLK source.
*/
static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
{
if (soc_is_s3c24xx())
return 1 << (tcfg1 + 1);
else
return 1 << tcfg1;
}
/**
* pwm_tdiv_has_div1() - does the tdiv setting have a /1
*
* Return true if we have a /1 in the tdiv setting.
*/
static inline unsigned int pwm_tdiv_has_div1(void)
{
if (soc_is_s3c24xx())
return 0;
else
return 1;
}
/**
* pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
* @div: The divisor to calculate the bit information for.
*
* Turn a divisor into the necessary bit field for TCFG1.
*/
static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
{
if (soc_is_s3c24xx())
return ilog2(div) - 1;
else
return ilog2(div);
}
#endif /* __ASM_PLAT_PWM_CLOCK_H */

View File

@@ -0,0 +1,68 @@
/* arch/arm/mach-s3c2410/include/mach/regs-adc.h
*
* Copyright (c) 2004 Shannon Holland <holland@loser.net>
*
* This program is free software; yosu 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.
*
* S3C2410 ADC registers
*/
#ifndef __ASM_ARCH_REGS_ADC_H
#define __ASM_ARCH_REGS_ADC_H "regs-adc.h"
#define S3C2410_ADCREG(x) (x)
#define S3C2410_ADCCON S3C2410_ADCREG(0x00)
#define S3C2410_ADCTSC S3C2410_ADCREG(0x04)
#define S3C2410_ADCDLY S3C2410_ADCREG(0x08)
#define S3C2410_ADCDAT0 S3C2410_ADCREG(0x0C)
#define S3C2410_ADCDAT1 S3C2410_ADCREG(0x10)
#define S3C64XX_ADCUPDN S3C2410_ADCREG(0x14)
#define S3C2443_ADCMUX S3C2410_ADCREG(0x18)
#define S3C64XX_ADCCLRINT S3C2410_ADCREG(0x18)
#define S5P_ADCMUX S3C2410_ADCREG(0x1C)
#define S3C64XX_ADCCLRINTPNDNUP S3C2410_ADCREG(0x20)
/* ADCCON Register Bits */
#define S3C64XX_ADCCON_RESSEL (1<<16)
#define S3C2410_ADCCON_ECFLG (1<<15)
#define S3C2410_ADCCON_PRSCEN (1<<14)
#define S3C2410_ADCCON_PRSCVL(x) (((x)&0xFF)<<6)
#define S3C2410_ADCCON_PRSCVLMASK (0xFF<<6)
#define S3C2410_ADCCON_SELMUX(x) (((x)&0x7)<<3)
#define S3C2410_ADCCON_MUXMASK (0x7<<3)
#define S3C2416_ADCCON_RESSEL (1 << 3)
#define S3C2410_ADCCON_STDBM (1<<2)
#define S3C2410_ADCCON_READ_START (1<<1)
#define S3C2410_ADCCON_ENABLE_START (1<<0)
#define S3C2410_ADCCON_STARTMASK (0x3<<0)
/* ADCTSC Register Bits */
#define S3C2443_ADCTSC_UD_SEN (1 << 8)
#define S3C2410_ADCTSC_YM_SEN (1<<7)
#define S3C2410_ADCTSC_YP_SEN (1<<6)
#define S3C2410_ADCTSC_XM_SEN (1<<5)
#define S3C2410_ADCTSC_XP_SEN (1<<4)
#define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3)
#define S3C2410_ADCTSC_AUTO_PST (1<<2)
#define S3C2410_ADCTSC_XY_PST(x) (((x)&0x3)<<0)
/* ADCDAT0 Bits */
#define S3C2410_ADCDAT0_UPDOWN (1<<15)
#define S3C2410_ADCDAT0_AUTO_PST (1<<14)
#define S3C2410_ADCDAT0_XY_PST (0x3<<12)
#define S3C2410_ADCDAT0_XPDATA_MASK (0x03FF)
/* ADCDAT1 Bits */
#define S3C2410_ADCDAT1_UPDOWN (1<<15)
#define S3C2410_ADCDAT1_AUTO_PST (1<<14)
#define S3C2410_ADCDAT1_XY_PST (0x3<<12)
#define S3C2410_ADCDAT1_YPDATA_MASK (0x03FF)
#endif /* __ASM_ARCH_REGS_ADC_H */

View File

@@ -0,0 +1,56 @@
/* linux/arch/arm/plat-samsung/include/plat/regs-ata.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung CF-ATA register definitions
*
* 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.
*/
#ifndef __ASM_PLAT_REGS_ATA_H
#define __ASM_PLAT_REGS_ATA_H __FILE__
#define S3C_CFATA_REG(x) (x)
#define S3C_CFATA_MUX S3C_CFATA_REG(0x0)
#define S3C_ATA_CTRL S3C_CFATA_REG(0x0)
#define S3C_ATA_STATUS S3C_CFATA_REG(0x4)
#define S3C_ATA_CMD S3C_CFATA_REG(0x8)
#define S3C_ATA_SWRST S3C_CFATA_REG(0xc)
#define S3C_ATA_IRQ S3C_CFATA_REG(0x10)
#define S3C_ATA_IRQ_MSK S3C_CFATA_REG(0x14)
#define S3C_ATA_CFG S3C_CFATA_REG(0x18)
#define S3C_ATA_MDMA_TIME S3C_CFATA_REG(0x28)
#define S3C_ATA_PIO_TIME S3C_CFATA_REG(0x2c)
#define S3C_ATA_UDMA_TIME S3C_CFATA_REG(0x30)
#define S3C_ATA_XFR_NUM S3C_CFATA_REG(0x34)
#define S3C_ATA_XFR_CNT S3C_CFATA_REG(0x38)
#define S3C_ATA_TBUF_START S3C_CFATA_REG(0x3c)
#define S3C_ATA_TBUF_SIZE S3C_CFATA_REG(0x40)
#define S3C_ATA_SBUF_START S3C_CFATA_REG(0x44)
#define S3C_ATA_SBUF_SIZE S3C_CFATA_REG(0x48)
#define S3C_ATA_CADR_TBUF S3C_CFATA_REG(0x4c)
#define S3C_ATA_CADR_SBUF S3C_CFATA_REG(0x50)
#define S3C_ATA_PIO_DTR S3C_CFATA_REG(0x54)
#define S3C_ATA_PIO_FED S3C_CFATA_REG(0x58)
#define S3C_ATA_PIO_SCR S3C_CFATA_REG(0x5c)
#define S3C_ATA_PIO_LLR S3C_CFATA_REG(0x60)
#define S3C_ATA_PIO_LMR S3C_CFATA_REG(0x64)
#define S3C_ATA_PIO_LHR S3C_CFATA_REG(0x68)
#define S3C_ATA_PIO_DVR S3C_CFATA_REG(0x6c)
#define S3C_ATA_PIO_CSD S3C_CFATA_REG(0x70)
#define S3C_ATA_PIO_DAD S3C_CFATA_REG(0x74)
#define S3C_ATA_PIO_READY S3C_CFATA_REG(0x78)
#define S3C_ATA_PIO_RDATA S3C_CFATA_REG(0x7c)
#define S3C_CFATA_MUX_TRUEIDE 0x01
#define S3C_ATA_CFG_SWAP 0x40
#define S3C_ATA_CFG_IORDYEN 0x02
#endif /* __ASM_PLAT_REGS_ATA_H */

View File

@@ -0,0 +1,151 @@
/* arch/arm/plat-samsung/include/plat/regs-dma.h
*
* Copyright (C) 2003-2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Samsung S3C24XX DMA support
*
* 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.
*/
#ifndef __ASM_PLAT_REGS_DMA_H
#define __ASM_PLAT_REGS_DMA_H __FILE__
#define S3C2410_DMA_DISRC (0x00)
#define S3C2410_DMA_DISRCC (0x04)
#define S3C2410_DMA_DIDST (0x08)
#define S3C2410_DMA_DIDSTC (0x0C)
#define S3C2410_DMA_DCON (0x10)
#define S3C2410_DMA_DSTAT (0x14)
#define S3C2410_DMA_DCSRC (0x18)
#define S3C2410_DMA_DCDST (0x1C)
#define S3C2410_DMA_DMASKTRIG (0x20)
#define S3C2412_DMA_DMAREQSEL (0x24)
#define S3C2443_DMA_DMAREQSEL (0x24)
#define S3C2410_DISRCC_INC (1 << 0)
#define S3C2410_DISRCC_APB (1 << 1)
#define S3C2410_DMASKTRIG_STOP (1 << 2)
#define S3C2410_DMASKTRIG_ON (1 << 1)
#define S3C2410_DMASKTRIG_SWTRIG (1 << 0)
#define S3C2410_DCON_DEMAND (0 << 31)
#define S3C2410_DCON_HANDSHAKE (1 << 31)
#define S3C2410_DCON_SYNC_PCLK (0 << 30)
#define S3C2410_DCON_SYNC_HCLK (1 << 30)
#define S3C2410_DCON_INTREQ (1 << 29)
#define S3C2410_DCON_CH0_XDREQ0 (0 << 24)
#define S3C2410_DCON_CH0_UART0 (1 << 24)
#define S3C2410_DCON_CH0_SDI (2 << 24)
#define S3C2410_DCON_CH0_TIMER (3 << 24)
#define S3C2410_DCON_CH0_USBEP1 (4 << 24)
#define S3C2410_DCON_CH1_XDREQ1 (0 << 24)
#define S3C2410_DCON_CH1_UART1 (1 << 24)
#define S3C2410_DCON_CH1_I2SSDI (2 << 24)
#define S3C2410_DCON_CH1_SPI (3 << 24)
#define S3C2410_DCON_CH1_USBEP2 (4 << 24)
#define S3C2410_DCON_CH2_I2SSDO (0 << 24)
#define S3C2410_DCON_CH2_I2SSDI (1 << 24)
#define S3C2410_DCON_CH2_SDI (2 << 24)
#define S3C2410_DCON_CH2_TIMER (3 << 24)
#define S3C2410_DCON_CH2_USBEP3 (4 << 24)
#define S3C2410_DCON_CH3_UART2 (0 << 24)
#define S3C2410_DCON_CH3_SDI (1 << 24)
#define S3C2410_DCON_CH3_SPI (2 << 24)
#define S3C2410_DCON_CH3_TIMER (3 << 24)
#define S3C2410_DCON_CH3_USBEP4 (4 << 24)
#define S3C2410_DCON_SRCSHIFT (24)
#define S3C2410_DCON_SRCMASK (7 << 24)
#define S3C2410_DCON_BYTE (0 << 20)
#define S3C2410_DCON_HALFWORD (1 << 20)
#define S3C2410_DCON_WORD (2 << 20)
#define S3C2410_DCON_AUTORELOAD (0 << 22)
#define S3C2410_DCON_NORELOAD (1 << 22)
#define S3C2410_DCON_HWTRIG (1 << 23)
#ifdef CONFIG_CPU_S3C2440
#define S3C2440_DIDSTC_CHKINT (1 << 2)
#define S3C2440_DCON_CH0_I2SSDO (5 << 24)
#define S3C2440_DCON_CH0_PCMIN (6 << 24)
#define S3C2440_DCON_CH1_PCMOUT (5 << 24)
#define S3C2440_DCON_CH1_SDI (6 << 24)
#define S3C2440_DCON_CH2_PCMIN (5 << 24)
#define S3C2440_DCON_CH2_MICIN (6 << 24)
#define S3C2440_DCON_CH3_MICIN (5 << 24)
#define S3C2440_DCON_CH3_PCMOUT (6 << 24)
#endif /* CONFIG_CPU_S3C2440 */
#ifdef CONFIG_CPU_S3C2412
#define S3C2412_DMAREQSEL_SRC(x) ((x) << 1)
#define S3C2412_DMAREQSEL_HW (1)
#define S3C2412_DMAREQSEL_SPI0TX S3C2412_DMAREQSEL_SRC(0)
#define S3C2412_DMAREQSEL_SPI0RX S3C2412_DMAREQSEL_SRC(1)
#define S3C2412_DMAREQSEL_SPI1TX S3C2412_DMAREQSEL_SRC(2)
#define S3C2412_DMAREQSEL_SPI1RX S3C2412_DMAREQSEL_SRC(3)
#define S3C2412_DMAREQSEL_I2STX S3C2412_DMAREQSEL_SRC(4)
#define S3C2412_DMAREQSEL_I2SRX S3C2412_DMAREQSEL_SRC(5)
#define S3C2412_DMAREQSEL_TIMER S3C2412_DMAREQSEL_SRC(9)
#define S3C2412_DMAREQSEL_SDI S3C2412_DMAREQSEL_SRC(10)
#define S3C2412_DMAREQSEL_USBEP1 S3C2412_DMAREQSEL_SRC(13)
#define S3C2412_DMAREQSEL_USBEP2 S3C2412_DMAREQSEL_SRC(14)
#define S3C2412_DMAREQSEL_USBEP3 S3C2412_DMAREQSEL_SRC(15)
#define S3C2412_DMAREQSEL_USBEP4 S3C2412_DMAREQSEL_SRC(16)
#define S3C2412_DMAREQSEL_XDREQ0 S3C2412_DMAREQSEL_SRC(17)
#define S3C2412_DMAREQSEL_XDREQ1 S3C2412_DMAREQSEL_SRC(18)
#define S3C2412_DMAREQSEL_UART0_0 S3C2412_DMAREQSEL_SRC(19)
#define S3C2412_DMAREQSEL_UART0_1 S3C2412_DMAREQSEL_SRC(20)
#define S3C2412_DMAREQSEL_UART1_0 S3C2412_DMAREQSEL_SRC(21)
#define S3C2412_DMAREQSEL_UART1_1 S3C2412_DMAREQSEL_SRC(22)
#define S3C2412_DMAREQSEL_UART2_0 S3C2412_DMAREQSEL_SRC(23)
#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24)
#endif /* CONFIG_CPU_S3C2412 */
#if defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2443)
#define S3C2443_DMAREQSEL_SRC(x) ((x) << 1)
#define S3C2443_DMAREQSEL_HW (1)
#define S3C2443_DMAREQSEL_SPI0TX S3C2443_DMAREQSEL_SRC(0)
#define S3C2443_DMAREQSEL_SPI0RX S3C2443_DMAREQSEL_SRC(1)
#define S3C2443_DMAREQSEL_SPI1TX S3C2443_DMAREQSEL_SRC(2)
#define S3C2443_DMAREQSEL_SPI1RX S3C2443_DMAREQSEL_SRC(3)
#define S3C2443_DMAREQSEL_I2STX S3C2443_DMAREQSEL_SRC(4)
#define S3C2443_DMAREQSEL_I2SRX S3C2443_DMAREQSEL_SRC(5)
#define S3C2443_DMAREQSEL_TIMER S3C2443_DMAREQSEL_SRC(9)
#define S3C2443_DMAREQSEL_SDI S3C2443_DMAREQSEL_SRC(10)
#define S3C2443_DMAREQSEL_XDREQ0 S3C2443_DMAREQSEL_SRC(17)
#define S3C2443_DMAREQSEL_XDREQ1 S3C2443_DMAREQSEL_SRC(18)
#define S3C2443_DMAREQSEL_UART0_0 S3C2443_DMAREQSEL_SRC(19)
#define S3C2443_DMAREQSEL_UART0_1 S3C2443_DMAREQSEL_SRC(20)
#define S3C2443_DMAREQSEL_UART1_0 S3C2443_DMAREQSEL_SRC(21)
#define S3C2443_DMAREQSEL_UART1_1 S3C2443_DMAREQSEL_SRC(22)
#define S3C2443_DMAREQSEL_UART2_0 S3C2443_DMAREQSEL_SRC(23)
#define S3C2443_DMAREQSEL_UART2_1 S3C2443_DMAREQSEL_SRC(24)
#define S3C2443_DMAREQSEL_UART3_0 S3C2443_DMAREQSEL_SRC(25)
#define S3C2443_DMAREQSEL_UART3_1 S3C2443_DMAREQSEL_SRC(26)
#define S3C2443_DMAREQSEL_PCMOUT S3C2443_DMAREQSEL_SRC(27)
#define S3C2443_DMAREQSEL_PCMIN S3C2443_DMAREQSEL_SRC(28)
#define S3C2443_DMAREQSEL_MICIN S3C2443_DMAREQSEL_SRC(29)
#endif /* CONFIG_CPU_S3C2443 */
#endif /* __ASM_PLAT_REGS_DMA_H */

View File

@@ -0,0 +1,21 @@
/* arch/arm/plat-s3c/include/plat/regs-irqtype.h
*
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* S3C - IRQ detection types.
*
* 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.
*/
/* values for S3C2410_EXTINT0/1/2 and other cpus in the series, including
* the S3C64XX
*/
#define S3C2410_EXTINT_LOWLEV (0x00)
#define S3C2410_EXTINT_HILEV (0x01)
#define S3C2410_EXTINT_FALLEDGE (0x02)
#define S3C2410_EXTINT_RISEEDGE (0x04)
#define S3C2410_EXTINT_BOTHEDGE (0x06)

View File

@@ -0,0 +1,123 @@
/* arch/arm/mach-s3c2410/include/mach/regs-nand.h
*
* Copyright (c) 2004-2005 Simtec Electronics <linux@simtec.co.uk>
* http://www.simtec.co.uk/products/SWLINUX/
*
* 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.
*
* S3C2410 NAND register definitions
*/
#ifndef __ASM_ARM_REGS_NAND
#define __ASM_ARM_REGS_NAND
#define S3C2410_NFREG(x) (x)
#define S3C2410_NFCONF S3C2410_NFREG(0x00)
#define S3C2410_NFCMD S3C2410_NFREG(0x04)
#define S3C2410_NFADDR S3C2410_NFREG(0x08)
#define S3C2410_NFDATA S3C2410_NFREG(0x0C)
#define S3C2410_NFSTAT S3C2410_NFREG(0x10)
#define S3C2410_NFECC S3C2410_NFREG(0x14)
#define S3C2440_NFCONT S3C2410_NFREG(0x04)
#define S3C2440_NFCMD S3C2410_NFREG(0x08)
#define S3C2440_NFADDR S3C2410_NFREG(0x0C)
#define S3C2440_NFDATA S3C2410_NFREG(0x10)
#define S3C2440_NFECCD0 S3C2410_NFREG(0x14)
#define S3C2440_NFECCD1 S3C2410_NFREG(0x18)
#define S3C2440_NFECCD S3C2410_NFREG(0x1C)
#define S3C2440_NFSTAT S3C2410_NFREG(0x20)
#define S3C2440_NFESTAT0 S3C2410_NFREG(0x24)
#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
#define S3C2440_NFMECC0 S3C2410_NFREG(0x2C)
#define S3C2440_NFMECC1 S3C2410_NFREG(0x30)
#define S3C2440_NFSECC S3C2410_NFREG(0x34)
#define S3C2440_NFSBLK S3C2410_NFREG(0x38)
#define S3C2440_NFEBLK S3C2410_NFREG(0x3C)
#define S3C2412_NFSBLK S3C2410_NFREG(0x20)
#define S3C2412_NFEBLK S3C2410_NFREG(0x24)
#define S3C2412_NFSTAT S3C2410_NFREG(0x28)
#define S3C2412_NFMECC_ERR0 S3C2410_NFREG(0x2C)
#define S3C2412_NFMECC_ERR1 S3C2410_NFREG(0x30)
#define S3C2412_NFMECC0 S3C2410_NFREG(0x34)
#define S3C2412_NFMECC1 S3C2410_NFREG(0x38)
#define S3C2412_NFSECC S3C2410_NFREG(0x3C)
#define S3C2410_NFCONF_EN (1<<15)
#define S3C2410_NFCONF_512BYTE (1<<14)
#define S3C2410_NFCONF_4STEP (1<<13)
#define S3C2410_NFCONF_INITECC (1<<12)
#define S3C2410_NFCONF_nFCE (1<<11)
#define S3C2410_NFCONF_TACLS(x) ((x)<<8)
#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4)
#define S3C2410_NFCONF_TWRPH1(x) ((x)<<0)
#define S3C2410_NFSTAT_BUSY (1<<0)
#define S3C2440_NFCONF_BUSWIDTH_8 (0<<0)
#define S3C2440_NFCONF_BUSWIDTH_16 (1<<0)
#define S3C2440_NFCONF_ADVFLASH (1<<3)
#define S3C2440_NFCONF_TACLS(x) ((x)<<12)
#define S3C2440_NFCONF_TWRPH0(x) ((x)<<8)
#define S3C2440_NFCONF_TWRPH1(x) ((x)<<4)
#define S3C2440_NFCONT_LOCKTIGHT (1<<13)
#define S3C2440_NFCONT_SOFTLOCK (1<<12)
#define S3C2440_NFCONT_ILLEGALACC_EN (1<<10)
#define S3C2440_NFCONT_RNBINT_EN (1<<9)
#define S3C2440_NFCONT_RN_FALLING (1<<8)
#define S3C2440_NFCONT_SPARE_ECCLOCK (1<<6)
#define S3C2440_NFCONT_MAIN_ECCLOCK (1<<5)
#define S3C2440_NFCONT_INITECC (1<<4)
#define S3C2440_NFCONT_nFCE (1<<1)
#define S3C2440_NFCONT_ENABLE (1<<0)
#define S3C2440_NFSTAT_READY (1<<0)
#define S3C2440_NFSTAT_nCE (1<<1)
#define S3C2440_NFSTAT_RnB_CHANGE (1<<2)
#define S3C2440_NFSTAT_ILLEGAL_ACCESS (1<<3)
#define S3C2412_NFCONF_NANDBOOT (1<<31)
#define S3C2412_NFCONF_ECCCLKCON (1<<30)
#define S3C2412_NFCONF_ECC_MLC (1<<24)
#define S3C2412_NFCONF_TACLS_MASK (7<<12) /* 1 extra bit of Tacls */
#define S3C2412_NFCONT_ECC4_DIRWR (1<<18)
#define S3C2412_NFCONT_LOCKTIGHT (1<<17)
#define S3C2412_NFCONT_SOFTLOCK (1<<16)
#define S3C2412_NFCONT_ECC4_ENCINT (1<<13)
#define S3C2412_NFCONT_ECC4_DECINT (1<<12)
#define S3C2412_NFCONT_MAIN_ECC_LOCK (1<<7)
#define S3C2412_NFCONT_INIT_MAIN_ECC (1<<5)
#define S3C2412_NFCONT_nFCE1 (1<<2)
#define S3C2412_NFCONT_nFCE0 (1<<1)
#define S3C2412_NFSTAT_ECC_ENCDONE (1<<7)
#define S3C2412_NFSTAT_ECC_DECDONE (1<<6)
#define S3C2412_NFSTAT_ILLEGAL_ACCESS (1<<5)
#define S3C2412_NFSTAT_RnB_CHANGE (1<<4)
#define S3C2412_NFSTAT_nFCE1 (1<<3)
#define S3C2412_NFSTAT_nFCE0 (1<<2)
#define S3C2412_NFSTAT_Res1 (1<<1)
#define S3C2412_NFSTAT_READY (1<<0)
#define S3C2412_NFECCERR_SERRDATA(x) (((x) >> 21) & 0xf)
#define S3C2412_NFECCERR_SERRBIT(x) (((x) >> 18) & 0x7)
#define S3C2412_NFECCERR_MERRDATA(x) (((x) >> 7) & 0x3ff)
#define S3C2412_NFECCERR_MERRBIT(x) (((x) >> 4) & 0x7)
#define S3C2412_NFECCERR_SPARE_ERR(x) (((x) >> 2) & 0x3)
#define S3C2412_NFECCERR_MAIN_ERR(x) (((x) >> 2) & 0x3)
#define S3C2412_NFECCERR_NONE (0)
#define S3C2412_NFECCERR_1BIT (1)
#define S3C2412_NFECCERR_MULTIBIT (2)
#define S3C2412_NFECCERR_ECCAREA (3)
#endif /* __ASM_ARM_REGS_NAND */

View File

@@ -0,0 +1 @@
#include <linux/serial_s3c.h>

View File

@@ -0,0 +1,48 @@
/* arch/arm/plat-samsung/include/plat/regs-spi.h
*
* Copyright (c) 2004 Fetron GmbH
*
* 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.
*
* S3C2410 SPI register definition
*/
#ifndef __ASM_ARCH_REGS_SPI_H
#define __ASM_ARCH_REGS_SPI_H
#define S3C2410_SPI1 (0x20)
#define S3C2412_SPI1 (0x100)
#define S3C2410_SPCON (0x00)
#define S3C2410_SPCON_SMOD_DMA (2 << 5) /* DMA mode */
#define S3C2410_SPCON_SMOD_INT (1 << 5) /* interrupt mode */
#define S3C2410_SPCON_SMOD_POLL (0 << 5) /* polling mode */
#define S3C2410_SPCON_ENSCK (1 << 4) /* Enable SCK */
#define S3C2410_SPCON_MSTR (1 << 3) /* Master:1, Slave:0 select */
#define S3C2410_SPCON_CPOL_HIGH (1 << 2) /* Clock polarity select */
#define S3C2410_SPCON_CPOL_LOW (0 << 2) /* Clock polarity select */
#define S3C2410_SPCON_CPHA_FMTB (1 << 1) /* Clock Phase Select */
#define S3C2410_SPCON_CPHA_FMTA (0 << 1) /* Clock Phase Select */
#define S3C2410_SPSTA (0x04)
#define S3C2410_SPSTA_DCOL (1 << 2) /* Data Collision Error */
#define S3C2410_SPSTA_MULD (1 << 1) /* Multi Master Error */
#define S3C2410_SPSTA_READY (1 << 0) /* Data Tx/Rx ready */
#define S3C2412_SPSTA_READY_ORG (1 << 3)
#define S3C2410_SPPIN (0x08)
#define S3C2410_SPPIN_ENMUL (1 << 2) /* Multi Master Error detect */
#define S3C2410_SPPIN_RESERVED (1 << 1)
#define S3C2410_SPPIN_KEEP (1 << 0) /* Master Out keep */
#define S3C2410_SPPRE (0x0C)
#define S3C2410_SPTDAT (0x10)
#define S3C2410_SPRDAT (0x14)
#endif /* __ASM_ARCH_REGS_SPI_H */

View File

@@ -0,0 +1,54 @@
/* linux/arch/arm/plat-samsung/include/plat/regs-srom.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* S5P SROMC register definitions
*
* 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.
*/
#ifndef __PLAT_SAMSUNG_REGS_SROM_H
#define __PLAT_SAMSUNG_REGS_SROM_H __FILE__
#include <mach/map.h>
#define S5P_SROMREG(x) (S5P_VA_SROMC + (x))
#define S5P_SROM_BW S5P_SROMREG(0x0)
#define S5P_SROM_BC0 S5P_SROMREG(0x4)
#define S5P_SROM_BC1 S5P_SROMREG(0x8)
#define S5P_SROM_BC2 S5P_SROMREG(0xc)
#define S5P_SROM_BC3 S5P_SROMREG(0x10)
#define S5P_SROM_BC4 S5P_SROMREG(0x14)
#define S5P_SROM_BC5 S5P_SROMREG(0x18)
/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
#define S5P_SROM_BW__DATAWIDTH__SHIFT 0
#define S5P_SROM_BW__ADDRMODE__SHIFT 1
#define S5P_SROM_BW__WAITENABLE__SHIFT 2
#define S5P_SROM_BW__BYTEENABLE__SHIFT 3
#define S5P_SROM_BW__CS_MASK 0xf
#define S5P_SROM_BW__NCS0__SHIFT 0
#define S5P_SROM_BW__NCS1__SHIFT 4
#define S5P_SROM_BW__NCS2__SHIFT 8
#define S5P_SROM_BW__NCS3__SHIFT 12
#define S5P_SROM_BW__NCS4__SHIFT 16
#define S5P_SROM_BW__NCS5__SHIFT 20
/* applies to same to BCS0 - BCS3 */
#define S5P_SROM_BCX__PMC__SHIFT 0
#define S5P_SROM_BCX__TACP__SHIFT 4
#define S5P_SROM_BCX__TCAH__SHIFT 8
#define S5P_SROM_BCX__TCOH__SHIFT 12
#define S5P_SROM_BCX__TACC__SHIFT 16
#define S5P_SROM_BCX__TCOS__SHIFT 24
#define S5P_SROM_BCX__TACS__SHIFT 28
#endif /* __PLAT_SAMSUNG_REGS_SROM_H */

View File

@@ -0,0 +1,124 @@
/* arch/arm/mach-s3c2410/include/mach/regs-timer.h
*
* Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
* http://www.simtec.co.uk/products/SWLINUX/
*
* 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.
*
* S3C2410 Timer configuration
*/
#ifndef __ASM_ARCH_REGS_TIMER_H
#define __ASM_ARCH_REGS_TIMER_H
#define S3C_TIMERREG(x) (S3C_VA_TIMER + (x))
#define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
#define S3C2410_TCFG0 S3C_TIMERREG(0x00)
#define S3C2410_TCFG1 S3C_TIMERREG(0x04)
#define S3C2410_TCON S3C_TIMERREG(0x08)
#define S3C64XX_TINT_CSTAT S3C_TIMERREG(0x44)
#define S3C2410_TCFG_PRESCALER0_MASK (255<<0)
#define S3C2410_TCFG_PRESCALER1_MASK (255<<8)
#define S3C2410_TCFG_PRESCALER1_SHIFT (8)
#define S3C2410_TCFG_DEADZONE_MASK (255<<16)
#define S3C2410_TCFG_DEADZONE_SHIFT (16)
#define S3C2410_TCFG1_MUX4_DIV2 (0<<16)
#define S3C2410_TCFG1_MUX4_DIV4 (1<<16)
#define S3C2410_TCFG1_MUX4_DIV8 (2<<16)
#define S3C2410_TCFG1_MUX4_DIV16 (3<<16)
#define S3C2410_TCFG1_MUX4_TCLK1 (4<<16)
#define S3C2410_TCFG1_MUX4_MASK (15<<16)
#define S3C2410_TCFG1_MUX4_SHIFT (16)
#define S3C2410_TCFG1_MUX3_DIV2 (0<<12)
#define S3C2410_TCFG1_MUX3_DIV4 (1<<12)
#define S3C2410_TCFG1_MUX3_DIV8 (2<<12)
#define S3C2410_TCFG1_MUX3_DIV16 (3<<12)
#define S3C2410_TCFG1_MUX3_TCLK1 (4<<12)
#define S3C2410_TCFG1_MUX3_MASK (15<<12)
#define S3C2410_TCFG1_MUX2_DIV2 (0<<8)
#define S3C2410_TCFG1_MUX2_DIV4 (1<<8)
#define S3C2410_TCFG1_MUX2_DIV8 (2<<8)
#define S3C2410_TCFG1_MUX2_DIV16 (3<<8)
#define S3C2410_TCFG1_MUX2_TCLK1 (4<<8)
#define S3C2410_TCFG1_MUX2_MASK (15<<8)
#define S3C2410_TCFG1_MUX1_DIV2 (0<<4)
#define S3C2410_TCFG1_MUX1_DIV4 (1<<4)
#define S3C2410_TCFG1_MUX1_DIV8 (2<<4)
#define S3C2410_TCFG1_MUX1_DIV16 (3<<4)
#define S3C2410_TCFG1_MUX1_TCLK0 (4<<4)
#define S3C2410_TCFG1_MUX1_MASK (15<<4)
#define S3C2410_TCFG1_MUX0_DIV2 (0<<0)
#define S3C2410_TCFG1_MUX0_DIV4 (1<<0)
#define S3C2410_TCFG1_MUX0_DIV8 (2<<0)
#define S3C2410_TCFG1_MUX0_DIV16 (3<<0)
#define S3C2410_TCFG1_MUX0_TCLK0 (4<<0)
#define S3C2410_TCFG1_MUX0_MASK (15<<0)
#define S3C2410_TCFG1_MUX_DIV2 (0<<0)
#define S3C2410_TCFG1_MUX_DIV4 (1<<0)
#define S3C2410_TCFG1_MUX_DIV8 (2<<0)
#define S3C2410_TCFG1_MUX_DIV16 (3<<0)
#define S3C2410_TCFG1_MUX_TCLK (4<<0)
#define S3C2410_TCFG1_MUX_MASK (15<<0)
#define S3C64XX_TCFG1_MUX_DIV1 (0<<0)
#define S3C64XX_TCFG1_MUX_DIV2 (1<<0)
#define S3C64XX_TCFG1_MUX_DIV4 (2<<0)
#define S3C64XX_TCFG1_MUX_DIV8 (3<<0)
#define S3C64XX_TCFG1_MUX_DIV16 (4<<0)
#define S3C64XX_TCFG1_MUX_TCLK (5<<0) /* 3 sets of TCLK */
#define S3C64XX_TCFG1_MUX_MASK (15<<0)
#define S3C2410_TCFG1_SHIFT(x) ((x) * 4)
/* for each timer, we have an count buffer, an compare buffer and
* an observation buffer
*/
/* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */
#define S3C2410_TCNTB(tmr) S3C_TIMERREG2(tmr, 0x00)
#define S3C2410_TCMPB(tmr) S3C_TIMERREG2(tmr, 0x04)
#define S3C2410_TCNTO(tmr) S3C_TIMERREG2(tmr, (((tmr) == 4) ? 0x04 : 0x08))
#define S3C2410_TCON_T4RELOAD (1<<22)
#define S3C2410_TCON_T4MANUALUPD (1<<21)
#define S3C2410_TCON_T4START (1<<20)
#define S3C2410_TCON_T3RELOAD (1<<19)
#define S3C2410_TCON_T3INVERT (1<<18)
#define S3C2410_TCON_T3MANUALUPD (1<<17)
#define S3C2410_TCON_T3START (1<<16)
#define S3C2410_TCON_T2RELOAD (1<<15)
#define S3C2410_TCON_T2INVERT (1<<14)
#define S3C2410_TCON_T2MANUALUPD (1<<13)
#define S3C2410_TCON_T2START (1<<12)
#define S3C2410_TCON_T1RELOAD (1<<11)
#define S3C2410_TCON_T1INVERT (1<<10)
#define S3C2410_TCON_T1MANUALUPD (1<<9)
#define S3C2410_TCON_T1START (1<<8)
#define S3C2410_TCON_T0DEADZONE (1<<4)
#define S3C2410_TCON_T0RELOAD (1<<3)
#define S3C2410_TCON_T0INVERT (1<<2)
#define S3C2410_TCON_T0MANUALUPD (1<<1)
#define S3C2410_TCON_T0START (1<<0)
#endif /* __ASM_ARCH_REGS_TIMER_H */

View File

@@ -0,0 +1,151 @@
/* arch/arm/plat-samsung/include/plat/regs-udc.h
*
* Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
*
* This include file 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.
*/
#ifndef __ASM_ARCH_REGS_UDC_H
#define __ASM_ARCH_REGS_UDC_H
#define S3C2410_USBDREG(x) (x)
#define S3C2410_UDC_FUNC_ADDR_REG S3C2410_USBDREG(0x0140)
#define S3C2410_UDC_PWR_REG S3C2410_USBDREG(0x0144)
#define S3C2410_UDC_EP_INT_REG S3C2410_USBDREG(0x0148)
#define S3C2410_UDC_USB_INT_REG S3C2410_USBDREG(0x0158)
#define S3C2410_UDC_EP_INT_EN_REG S3C2410_USBDREG(0x015c)
#define S3C2410_UDC_USB_INT_EN_REG S3C2410_USBDREG(0x016c)
#define S3C2410_UDC_FRAME_NUM1_REG S3C2410_USBDREG(0x0170)
#define S3C2410_UDC_FRAME_NUM2_REG S3C2410_USBDREG(0x0174)
#define S3C2410_UDC_EP0_FIFO_REG S3C2410_USBDREG(0x01c0)
#define S3C2410_UDC_EP1_FIFO_REG S3C2410_USBDREG(0x01c4)
#define S3C2410_UDC_EP2_FIFO_REG S3C2410_USBDREG(0x01c8)
#define S3C2410_UDC_EP3_FIFO_REG S3C2410_USBDREG(0x01cc)
#define S3C2410_UDC_EP4_FIFO_REG S3C2410_USBDREG(0x01d0)
#define S3C2410_UDC_EP1_DMA_CON S3C2410_USBDREG(0x0200)
#define S3C2410_UDC_EP1_DMA_UNIT S3C2410_USBDREG(0x0204)
#define S3C2410_UDC_EP1_DMA_FIFO S3C2410_USBDREG(0x0208)
#define S3C2410_UDC_EP1_DMA_TTC_L S3C2410_USBDREG(0x020c)
#define S3C2410_UDC_EP1_DMA_TTC_M S3C2410_USBDREG(0x0210)
#define S3C2410_UDC_EP1_DMA_TTC_H S3C2410_USBDREG(0x0214)
#define S3C2410_UDC_EP2_DMA_CON S3C2410_USBDREG(0x0218)
#define S3C2410_UDC_EP2_DMA_UNIT S3C2410_USBDREG(0x021c)
#define S3C2410_UDC_EP2_DMA_FIFO S3C2410_USBDREG(0x0220)
#define S3C2410_UDC_EP2_DMA_TTC_L S3C2410_USBDREG(0x0224)
#define S3C2410_UDC_EP2_DMA_TTC_M S3C2410_USBDREG(0x0228)
#define S3C2410_UDC_EP2_DMA_TTC_H S3C2410_USBDREG(0x022c)
#define S3C2410_UDC_EP3_DMA_CON S3C2410_USBDREG(0x0240)
#define S3C2410_UDC_EP3_DMA_UNIT S3C2410_USBDREG(0x0244)
#define S3C2410_UDC_EP3_DMA_FIFO S3C2410_USBDREG(0x0248)
#define S3C2410_UDC_EP3_DMA_TTC_L S3C2410_USBDREG(0x024c)
#define S3C2410_UDC_EP3_DMA_TTC_M S3C2410_USBDREG(0x0250)
#define S3C2410_UDC_EP3_DMA_TTC_H S3C2410_USBDREG(0x0254)
#define S3C2410_UDC_EP4_DMA_CON S3C2410_USBDREG(0x0258)
#define S3C2410_UDC_EP4_DMA_UNIT S3C2410_USBDREG(0x025c)
#define S3C2410_UDC_EP4_DMA_FIFO S3C2410_USBDREG(0x0260)
#define S3C2410_UDC_EP4_DMA_TTC_L S3C2410_USBDREG(0x0264)
#define S3C2410_UDC_EP4_DMA_TTC_M S3C2410_USBDREG(0x0268)
#define S3C2410_UDC_EP4_DMA_TTC_H S3C2410_USBDREG(0x026c)
#define S3C2410_UDC_INDEX_REG S3C2410_USBDREG(0x0178)
/* indexed registers */
#define S3C2410_UDC_MAXP_REG S3C2410_USBDREG(0x0180)
#define S3C2410_UDC_EP0_CSR_REG S3C2410_USBDREG(0x0184)
#define S3C2410_UDC_IN_CSR1_REG S3C2410_USBDREG(0x0184)
#define S3C2410_UDC_IN_CSR2_REG S3C2410_USBDREG(0x0188)
#define S3C2410_UDC_OUT_CSR1_REG S3C2410_USBDREG(0x0190)
#define S3C2410_UDC_OUT_CSR2_REG S3C2410_USBDREG(0x0194)
#define S3C2410_UDC_OUT_FIFO_CNT1_REG S3C2410_USBDREG(0x0198)
#define S3C2410_UDC_OUT_FIFO_CNT2_REG S3C2410_USBDREG(0x019c)
#define S3C2410_UDC_FUNCADDR_UPDATE (1 << 7)
#define S3C2410_UDC_PWR_ISOUP (1 << 7) /* R/W */
#define S3C2410_UDC_PWR_RESET (1 << 3) /* R */
#define S3C2410_UDC_PWR_RESUME (1 << 2) /* R/W */
#define S3C2410_UDC_PWR_SUSPEND (1 << 1) /* R */
#define S3C2410_UDC_PWR_ENSUSPEND (1 << 0) /* R/W */
#define S3C2410_UDC_PWR_DEFAULT (0x00)
#define S3C2410_UDC_INT_EP4 (1 << 4) /* R/W (clear only) */
#define S3C2410_UDC_INT_EP3 (1 << 3) /* R/W (clear only) */
#define S3C2410_UDC_INT_EP2 (1 << 2) /* R/W (clear only) */
#define S3C2410_UDC_INT_EP1 (1 << 1) /* R/W (clear only) */
#define S3C2410_UDC_INT_EP0 (1 << 0) /* R/W (clear only) */
#define S3C2410_UDC_USBINT_RESET (1 << 2) /* R/W (clear only) */
#define S3C2410_UDC_USBINT_RESUME (1 << 1) /* R/W (clear only) */
#define S3C2410_UDC_USBINT_SUSPEND (1 << 0) /* R/W (clear only) */
#define S3C2410_UDC_INTE_EP4 (1 << 4) /* R/W */
#define S3C2410_UDC_INTE_EP3 (1 << 3) /* R/W */
#define S3C2410_UDC_INTE_EP2 (1 << 2) /* R/W */
#define S3C2410_UDC_INTE_EP1 (1 << 1) /* R/W */
#define S3C2410_UDC_INTE_EP0 (1 << 0) /* R/W */
#define S3C2410_UDC_USBINTE_RESET (1 << 2) /* R/W */
#define S3C2410_UDC_USBINTE_SUSPEND (1 << 0) /* R/W */
#define S3C2410_UDC_INDEX_EP0 (0x00)
#define S3C2410_UDC_INDEX_EP1 (0x01)
#define S3C2410_UDC_INDEX_EP2 (0x02)
#define S3C2410_UDC_INDEX_EP3 (0x03)
#define S3C2410_UDC_INDEX_EP4 (0x04)
#define S3C2410_UDC_ICSR1_CLRDT (1 << 6) /* R/W */
#define S3C2410_UDC_ICSR1_SENTSTL (1 << 5) /* R/W (clear only) */
#define S3C2410_UDC_ICSR1_SENDSTL (1 << 4) /* R/W */
#define S3C2410_UDC_ICSR1_FFLUSH (1 << 3) /* W (set only) */
#define S3C2410_UDC_ICSR1_UNDRUN (1 << 2) /* R/W (clear only) */
#define S3C2410_UDC_ICSR1_PKTRDY (1 << 0) /* R/W (set only) */
#define S3C2410_UDC_ICSR2_AUTOSET (1 << 7) /* R/W */
#define S3C2410_UDC_ICSR2_ISO (1 << 6) /* R/W */
#define S3C2410_UDC_ICSR2_MODEIN (1 << 5) /* R/W */
#define S3C2410_UDC_ICSR2_DMAIEN (1 << 4) /* R/W */
#define S3C2410_UDC_OCSR1_CLRDT (1 << 7) /* R/W */
#define S3C2410_UDC_OCSR1_SENTSTL (1 << 6) /* R/W (clear only) */
#define S3C2410_UDC_OCSR1_SENDSTL (1 << 5) /* R/W */
#define S3C2410_UDC_OCSR1_FFLUSH (1 << 4) /* R/W */
#define S3C2410_UDC_OCSR1_DERROR (1 << 3) /* R */
#define S3C2410_UDC_OCSR1_OVRRUN (1 << 2) /* R/W (clear only) */
#define S3C2410_UDC_OCSR1_PKTRDY (1 << 0) /* R/W (clear only) */
#define S3C2410_UDC_OCSR2_AUTOCLR (1 << 7) /* R/W */
#define S3C2410_UDC_OCSR2_ISO (1 << 6) /* R/W */
#define S3C2410_UDC_OCSR2_DMAIEN (1 << 5) /* R/W */
#define S3C2410_UDC_EP0_CSR_OPKRDY (1 << 0)
#define S3C2410_UDC_EP0_CSR_IPKRDY (1 << 1)
#define S3C2410_UDC_EP0_CSR_SENTSTL (1 << 2)
#define S3C2410_UDC_EP0_CSR_DE (1 << 3)
#define S3C2410_UDC_EP0_CSR_SE (1 << 4)
#define S3C2410_UDC_EP0_CSR_SENDSTL (1 << 5)
#define S3C2410_UDC_EP0_CSR_SOPKTRDY (1 << 6)
#define S3C2410_UDC_EP0_CSR_SSE (1 << 7)
#define S3C2410_UDC_MAXP_8 (1 << 0)
#define S3C2410_UDC_MAXP_16 (1 << 1)
#define S3C2410_UDC_MAXP_32 (1 << 2)
#define S3C2410_UDC_MAXP_64 (1 << 3)
#endif

View File

@@ -0,0 +1,51 @@
/* arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C - USB2.0 Highspeed/OtG device PHY registers
*
* 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.
*/
/* Note, this is a separate header file as some of the clock framework
* needs to touch this if the clk_48m is used as the USB OHCI or other
* peripheral source.
*/
#ifndef __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H
#define __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H __FILE__
/* S3C64XX_PA_USB_HSPHY */
#define S3C_HSOTG_PHYREG(x) ((x) + S3C_VA_USB_HSPHY)
#define S3C_PHYPWR S3C_HSOTG_PHYREG(0x00)
#define S3C_PHYPWR_NORMAL_MASK (0x19 << 0)
#define S3C_PHYPWR_OTG_DISABLE (1 << 4)
#define S3C_PHYPWR_ANALOG_POWERDOWN (1 << 3)
#define SRC_PHYPWR_FORCE_SUSPEND (1 << 1)
#define S3C_PHYCLK S3C_HSOTG_PHYREG(0x04)
#define S3C_PHYCLK_MODE_USB11 (1 << 6)
#define S3C_PHYCLK_EXT_OSC (1 << 5)
#define S3C_PHYCLK_CLK_FORCE (1 << 4)
#define S3C_PHYCLK_ID_PULL (1 << 2)
#define S3C_PHYCLK_CLKSEL_MASK (0x3 << 0)
#define S3C_PHYCLK_CLKSEL_SHIFT (0)
#define S3C_PHYCLK_CLKSEL_48M (0x0 << 0)
#define S3C_PHYCLK_CLKSEL_12M (0x2 << 0)
#define S3C_PHYCLK_CLKSEL_24M (0x3 << 0)
#define S3C_RSTCON S3C_HSOTG_PHYREG(0x08)
#define S3C_RSTCON_PHYCLK (1 << 2)
#define S3C_RSTCON_HCLK (1 << 1)
#define S3C_RSTCON_PHY (1 << 0)
#define S3C_PHYTUNE S3C_HSOTG_PHYREG(0x20)
#endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H */

View File

@@ -0,0 +1,41 @@
/* arch/arm/mach-s3c2410/include/mach/regs-watchdog.h
*
* Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
* http://www.simtec.co.uk/products/SWLINUX/
*
* 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.
*
* S3C2410 Watchdog timer control
*/
#ifndef __ASM_ARCH_REGS_WATCHDOG_H
#define __ASM_ARCH_REGS_WATCHDOG_H
#define S3C_WDOGREG(x) ((x) + S3C_VA_WATCHDOG)
#define S3C2410_WTCON S3C_WDOGREG(0x00)
#define S3C2410_WTDAT S3C_WDOGREG(0x04)
#define S3C2410_WTCNT S3C_WDOGREG(0x08)
/* the watchdog can either generate a reset pulse, or an
* interrupt.
*/
#define S3C2410_WTCON_RSTEN (0x01)
#define S3C2410_WTCON_INTEN (1<<2)
#define S3C2410_WTCON_ENABLE (1<<5)
#define S3C2410_WTCON_DIV16 (0<<3)
#define S3C2410_WTCON_DIV32 (1<<3)
#define S3C2410_WTCON_DIV64 (2<<3)
#define S3C2410_WTCON_DIV128 (3<<3)
#define S3C2410_WTCON_PRESCALE(x) ((x) << 8)
#define S3C2410_WTCON_PRESCALE_MASK (0xff00)
#endif /* __ASM_ARCH_REGS_WATCHDOG_H */

View File

@@ -0,0 +1,27 @@
/* linux/arch/arm/plat-samsung/include/plat/rtc-core.h
*
* Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de>
*
* Samsung RTC Controller core functions
*
* 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.
*/
#ifndef __ASM_PLAT_RTC_CORE_H
#define __ASM_PLAT_RTC_CORE_H __FILE__
/* These functions are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void s3c_rtc_setname(char *name)
{
#if defined(CONFIG_S3C_DEV_RTC) || defined(CONFIG_PLAT_S3C24XX)
s3c_device_rtc.name = name;
#endif
}
#endif /* __ASM_PLAT_RTC_CORE_H */

View File

@@ -0,0 +1,65 @@
/* linux/arch/arm/plat-samsung/include/plat/s5p-clock.h
*
* Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Header file for s5p clock support
*
* 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.
*/
#ifndef __ASM_PLAT_S5P_CLOCK_H
#define __ASM_PLAT_S5P_CLOCK_H __FILE__
#include <linux/clk.h>
#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
#define clk_fin_apll clk_ext_xtal_mux
#define clk_fin_bpll clk_ext_xtal_mux
#define clk_fin_cpll clk_ext_xtal_mux
#define clk_fin_mpll clk_ext_xtal_mux
#define clk_fin_epll clk_ext_xtal_mux
#define clk_fin_dpll clk_ext_xtal_mux
#define clk_fin_vpll clk_ext_xtal_mux
#define clk_fin_hpll clk_ext_xtal_mux
extern struct clk clk_ext_xtal_mux;
extern struct clk clk_xusbxti;
extern struct clk clk_48m;
extern struct clk s5p_clk_27m;
extern struct clk clk_fout_apll;
extern struct clk clk_fout_bpll;
extern struct clk clk_fout_bpll_div2;
extern struct clk clk_fout_cpll;
extern struct clk clk_fout_mpll;
extern struct clk clk_fout_mpll_div2;
extern struct clk clk_fout_epll;
extern struct clk clk_fout_dpll;
extern struct clk clk_fout_vpll;
extern struct clk clk_arm;
extern struct clk clk_vpll;
extern struct clksrc_sources clk_src_apll;
extern struct clksrc_sources clk_src_bpll;
extern struct clksrc_sources clk_src_bpll_fout;
extern struct clksrc_sources clk_src_cpll;
extern struct clksrc_sources clk_src_mpll;
extern struct clksrc_sources clk_src_mpll_fout;
extern struct clksrc_sources clk_src_epll;
extern struct clksrc_sources clk_src_dpll;
extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
/* Common EPLL operations for S5P platform */
extern int s5p_epll_enable(struct clk *clk, int enable);
extern unsigned long s5p_epll_get_rate(struct clk *clk);
/* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */
extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
extern unsigned long s5p_spdif_get_rate(struct clk *clk);
extern struct clk_ops s5p_sclk_spdif_ops;
#endif /* __ASM_PLAT_S5P_CLOCK_H */

View File

@@ -0,0 +1,53 @@
/* linux/arch/arm/plat-samsung/include/plat/samsung-time.h
*
* Copyright 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* Header file for samsung s3c and s5p time support
*
* 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.
*/
#ifndef __ASM_PLAT_SAMSUNG_TIME_H
#define __ASM_PLAT_SAMSUNG_TIME_H __FILE__
/* SAMSUNG HR-Timer Clock mode */
enum samsung_timer_mode {
SAMSUNG_PWM0,
SAMSUNG_PWM1,
SAMSUNG_PWM2,
SAMSUNG_PWM3,
SAMSUNG_PWM4,
};
struct samsung_timer_source {
unsigned int event_id;
unsigned int source_id;
};
/* Be able to sleep for atleast 4 seconds (usually more) */
#define SAMSUNG_TIMER_MIN_RANGE 4
#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S5PC100)
#define TCNT_MAX 0xffff
#define TSCALER_DIV 25
#define TDIV 50
#define TSIZE 16
#else
#define TCNT_MAX 0xffffffff
#define TSCALER_DIV 2
#define TDIV 2
#define TSIZE 32
#endif
#define NON_PERIODIC 0
#define PERIODIC 1
extern void __init samsung_set_timer_source(enum samsung_timer_mode event,
enum samsung_timer_mode source);
extern void __init samsung_timer_init(void);
#endif /* __ASM_PLAT_SAMSUNG_TIME_H */

View File

@@ -0,0 +1,328 @@
/* linux/arch/arm/plat-samsung/include/plat/sdhci.h
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C Platform - SDHCI (HSMMC) platform data definitions
*
* 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.
*/
#ifndef __PLAT_S3C_SDHCI_H
#define __PLAT_S3C_SDHCI_H __FILE__
#include <linux/platform_data/mmc-sdhci-s3c.h>
#include <plat/devs.h>
/* s3c_sdhci_set_platdata() - common helper for setting SDHCI platform data
* @pd: The default platform data for this device.
* @set: Pointer to the platform data to fill in.
*/
extern void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
struct s3c_sdhci_platdata *set);
/**
* s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
* @pd: Platform data to register to device.
*
* Register the given platform data for use withe S3C SDHCI device.
* The call will copy the platform data, so the board definitions can
* make the structure itself __initdata.
*/
extern void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd);
extern void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd);
extern void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd);
extern void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd);
/* Default platform data, exported so that per-cpu initialisation can
* set the correct one when there are more than one cpu type selected.
*/
extern struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata;
extern struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata;
extern struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata;
extern struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata;
/* Helper function availability */
extern void s3c2416_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
extern void s3c2416_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
extern void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
extern void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
extern void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
extern void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
extern void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
extern void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
extern void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
extern void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
extern void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
extern void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
extern void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
extern void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
extern void s5p64x0_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
extern void s5p64x0_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
extern void s5p6440_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
extern void s5p6450_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
/* S3C2416 SDHCI setup */
#ifdef CONFIG_S3C2416_SETUP_SDHCI
static inline void s3c2416_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.cfg_gpio = s3c2416_setup_sdhci0_cfg_gpio;
#endif /* CONFIG_S3C_DEV_HSMMC */
}
static inline void s3c2416_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.cfg_gpio = s3c2416_setup_sdhci1_cfg_gpio;
#endif /* CONFIG_S3C_DEV_HSMMC1 */
}
#else
static inline void s3c2416_default_sdhci0(void) { }
static inline void s3c2416_default_sdhci1(void) { }
#endif /* CONFIG_S3C2416_SETUP_SDHCI */
/* S3C64XX SDHCI setup */
#ifdef CONFIG_S3C64XX_SETUP_SDHCI
static inline void s3c6400_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
#endif
}
static inline void s3c6400_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
#endif
}
static inline void s3c6400_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
#endif
}
static inline void s3c6410_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
#endif
}
static inline void s3c6410_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
#endif
}
static inline void s3c6410_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
#endif
}
#else
static inline void s3c6410_default_sdhci0(void) { }
static inline void s3c6410_default_sdhci1(void) { }
static inline void s3c6410_default_sdhci2(void) { }
static inline void s3c6400_default_sdhci0(void) { }
static inline void s3c6400_default_sdhci1(void) { }
static inline void s3c6400_default_sdhci2(void) { }
#endif /* CONFIG_S3C64XX_SETUP_SDHCI */
/* S5P64X0 SDHCI setup */
#ifdef CONFIG_S5P64X0_SETUP_SDHCI_GPIO
static inline void s5p64x0_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.cfg_gpio = s5p64x0_setup_sdhci0_cfg_gpio;
#endif
}
static inline void s5p64x0_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.cfg_gpio = s5p64x0_setup_sdhci1_cfg_gpio;
#endif
}
static inline void s5p6440_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.cfg_gpio = s5p6440_setup_sdhci2_cfg_gpio;
#endif
}
static inline void s5p6450_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.cfg_gpio = s5p6450_setup_sdhci2_cfg_gpio;
#endif
}
#else
static inline void s5p64x0_default_sdhci0(void) { }
static inline void s5p64x0_default_sdhci1(void) { }
static inline void s5p6440_default_sdhci2(void) { }
static inline void s5p6450_default_sdhci2(void) { }
#endif /* CONFIG_S5P64X0_SETUP_SDHCI_GPIO */
/* S5PC100 SDHCI setup */
#ifdef CONFIG_S5PC100_SETUP_SDHCI
static inline void s5pc100_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.cfg_gpio = s5pc100_setup_sdhci0_cfg_gpio;
#endif
}
static inline void s5pc100_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.cfg_gpio = s5pc100_setup_sdhci1_cfg_gpio;
#endif
}
static inline void s5pc100_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.cfg_gpio = s5pc100_setup_sdhci2_cfg_gpio;
#endif
}
#else
static inline void s5pc100_default_sdhci0(void) { }
static inline void s5pc100_default_sdhci1(void) { }
static inline void s5pc100_default_sdhci2(void) { }
#endif /* CONFIG_S5PC100_SETUP_SDHCI */
/* S5PV210 SDHCI setup */
#ifdef CONFIG_S5PV210_SETUP_SDHCI
static inline void s5pv210_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.cfg_gpio = s5pv210_setup_sdhci0_cfg_gpio;
#endif
}
static inline void s5pv210_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.cfg_gpio = s5pv210_setup_sdhci1_cfg_gpio;
#endif
}
static inline void s5pv210_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.cfg_gpio = s5pv210_setup_sdhci2_cfg_gpio;
#endif
}
static inline void s5pv210_default_sdhci3(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC3
s3c_hsmmc3_def_platdata.cfg_gpio = s5pv210_setup_sdhci3_cfg_gpio;
#endif
}
#else
static inline void s5pv210_default_sdhci0(void) { }
static inline void s5pv210_default_sdhci1(void) { }
static inline void s5pv210_default_sdhci2(void) { }
static inline void s5pv210_default_sdhci3(void) { }
#endif /* CONFIG_S5PV210_SETUP_SDHCI */
/* EXYNOS4 SDHCI setup */
#ifdef CONFIG_EXYNOS4_SETUP_SDHCI
static inline void exynos4_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.cfg_gpio = exynos4_setup_sdhci0_cfg_gpio;
#endif
}
static inline void exynos4_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.cfg_gpio = exynos4_setup_sdhci1_cfg_gpio;
#endif
}
static inline void exynos4_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.cfg_gpio = exynos4_setup_sdhci2_cfg_gpio;
#endif
}
static inline void exynos4_default_sdhci3(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC3
s3c_hsmmc3_def_platdata.cfg_gpio = exynos4_setup_sdhci3_cfg_gpio;
#endif
}
#else
static inline void exynos4_default_sdhci0(void) { }
static inline void exynos4_default_sdhci1(void) { }
static inline void exynos4_default_sdhci2(void) { }
static inline void exynos4_default_sdhci3(void) { }
#endif /* CONFIG_EXYNOS4_SETUP_SDHCI */
static inline void s3c_sdhci_setname(int id, char *name)
{
switch (id) {
#ifdef CONFIG_S3C_DEV_HSMMC
case 0:
s3c_device_hsmmc0.name = name;
break;
#endif
#ifdef CONFIG_S3C_DEV_HSMMC1
case 1:
s3c_device_hsmmc1.name = name;
break;
#endif
#ifdef CONFIG_S3C_DEV_HSMMC2
case 2:
s3c_device_hsmmc2.name = name;
break;
#endif
#ifdef CONFIG_S3C_DEV_HSMMC3
case 3:
s3c_device_hsmmc3.name = name;
break;
#endif
default:
break;
}
}
#endif /* __PLAT_S3C_SDHCI_H */

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
*
* 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.
*/
#ifndef __PLAT_S3C_SPI_CORE_H
#define __PLAT_S3C_SPI_CORE_H
/* These functions are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void s3c64xx_spi_setname(char *name)
{
#ifdef CONFIG_S3C64XX_DEV_SPI0
s3c64xx_device_spi0.name = name;
#endif
#ifdef CONFIG_S3C64XX_DEV_SPI1
s3c64xx_device_spi1.name = name;
#endif
#ifdef CONFIG_S3C64XX_DEV_SPI2
s3c64xx_device_spi2.name = name;
#endif
}
#endif /* __PLAT_S3C_SPI_CORE_H */

View File

@@ -0,0 +1,44 @@
/*
* arch/arm/plat-samsung/include/plat/tv.h
*
* Copyright 2011 Samsung Electronics Co., Ltd.
* Tomasz Stanislawski <t.stanislaws@samsung.com>
*
* Samsung TV driver core functions
*
* 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.
*/
#ifndef __SAMSUNG_PLAT_TV_H
#define __SAMSUNG_PLAT_TV_H __FILE__
/*
* These functions are only for use with the core support code, such as
* the CPU-specific initialization code.
*/
/* Re-define device name to differentiate the subsystem in various SoCs. */
static inline void s5p_hdmi_setname(char *name)
{
#ifdef CONFIG_S5P_DEV_TV
s5p_device_hdmi.name = name;
#endif
}
static inline void s5p_mixer_setname(char *name)
{
#ifdef CONFIG_S5P_DEV_TV
s5p_device_mixer.name = name;
#endif
}
static inline void s5p_sdo_setname(char *name)
{
#ifdef CONFIG_S5P_DEV_TV
s5p_device_sdo.name = name;
#endif
}
#endif /* __SAMSUNG_PLAT_TV_H */

View File

@@ -0,0 +1,166 @@
/* arch/arm/plat-samsung/include/plat/uncompress.h
*
* Copyright 2003, 2007 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C - uncompress code
*
* 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.
*/
#ifndef __ASM_PLAT_UNCOMPRESS_H
#define __ASM_PLAT_UNCOMPRESS_H
typedef unsigned int upf_t; /* cannot include linux/serial_core.h */
/* uart setup */
unsigned int fifo_mask;
unsigned int fifo_max;
/* forward declerations */
static void arch_detect_cpu(void);
/* defines for UART registers */
#include <plat/regs-serial.h>
#include <plat/regs-watchdog.h>
/* working in physical space... */
#undef S3C2410_WDOGREG
#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x)))
/* how many bytes we allow into the FIFO at a time in FIFO mode */
#define FIFO_MAX (14)
#ifdef S3C_PA_UART
#define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT)
#endif
static __inline__ void
uart_wr(unsigned int reg, unsigned int val)
{
volatile unsigned int *ptr;
ptr = (volatile unsigned int *)(reg + uart_base);
*ptr = val;
}
static __inline__ unsigned int
uart_rd(unsigned int reg)
{
volatile unsigned int *ptr;
ptr = (volatile unsigned int *)(reg + uart_base);
return *ptr;
}
/* we can deal with the case the UARTs are being run
* in FIFO mode, so that we don't hold up our execution
* waiting for tx to happen...
*/
static void putc(int ch)
{
if (!config_enabled(CONFIG_DEBUG_LL))
return;
if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
int level;
while (1) {
level = uart_rd(S3C2410_UFSTAT);
level &= fifo_mask;
if (level < fifo_max)
break;
}
} else {
/* not using fifos */
while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
barrier();
}
/* write byte to transmission register */
uart_wr(S3C2410_UTXH, ch);
}
static inline void flush(void)
{
}
#define __raw_writel(d, ad) \
do { \
*((volatile unsigned int __force *)(ad)) = (d); \
} while (0)
#ifdef CONFIG_S3C_BOOT_ERROR_RESET
static void arch_decomp_error(const char *x)
{
putstr("\n\n");
putstr(x);
putstr("\n\n -- System resetting\n");
__raw_writel(0x4000, S3C2410_WTDAT);
__raw_writel(0x4000, S3C2410_WTCNT);
__raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
while(1);
}
#define arch_error arch_decomp_error
#endif
#ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO
static inline void arch_enable_uart_fifo(void)
{
u32 fifocon;
if (!config_enabled(CONFIG_DEBUG_LL))
return;
fifocon = uart_rd(S3C2410_UFCON);
if (!(fifocon & S3C2410_UFCON_FIFOMODE)) {
fifocon |= S3C2410_UFCON_RESETBOTH;
uart_wr(S3C2410_UFCON, fifocon);
/* wait for fifo reset to complete */
while (1) {
fifocon = uart_rd(S3C2410_UFCON);
if (!(fifocon & S3C2410_UFCON_RESETBOTH))
break;
}
}
}
#else
#define arch_enable_uart_fifo() do { } while(0)
#endif
static void
arch_decomp_setup(void)
{
/* we may need to setup the uart(s) here if we are not running
* on an BAST... the BAST will have left the uarts configured
* after calling linux.
*/
arch_detect_cpu();
/* Enable the UART FIFOs if they where not enabled and our
* configuration says we should turn them on.
*/
arch_enable_uart_fifo();
}
#endif /* __ASM_PLAT_UNCOMPRESS_H */

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2011 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* 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.
*/
#ifndef __PLAT_SAMSUNG_USB_PHY_H
#define __PLAT_SAMSUNG_USB_PHY_H __FILE__
#include <linux/usb/samsung_usb_phy.h>
extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
#endif /* __PLAT_SAMSUNG_USB_PHY_H */

View File

@@ -0,0 +1,44 @@
/* arch/arm/plat-samsung/include/plat/wakeup-mask.h
*
* Copyright 2010 Ben Dooks <ben-linux@fluff.org>
*
* Support for wakeup mask interrupts on newer SoCs
*
* 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.
*
*/
#ifndef __PLAT_WAKEUP_MASK_H
#define __PLAT_WAKEUP_MASK_H __file__
/* if no irq yet defined, but still want to mask */
#define NO_WAKEUP_IRQ (0x90000000)
/**
* struct samsung_wakeup_mask - wakeup mask information
* @irq: The interrupt associated with this wakeup.
* @bit: The bit, as a (1 << bitno) controlling this source.
*/
struct samsung_wakeup_mask {
unsigned int irq;
u32 bit;
};
/**
* samsung_sync_wakemask - sync wakeup mask information for pm
* @reg: The register that is used.
* @masks: The list of masks to use.
* @nr_masks: The number of entries pointed to buy @masks.
*
* Synchronise the wakeup mask information at suspend time from the list
* of interrupts and control bits in @masks. We do this at suspend time
* as overriding the relevant irq chips is harder and the register is only
* required to be correct before we enter sleep.
*/
extern void samsung_sync_wakemask(void __iomem *reg,
struct samsung_wakeup_mask *masks,
int nr_masks);
#endif /* __PLAT_WAKEUP_MASK_H */

View File

@@ -0,0 +1,46 @@
/* arch/arm/plat-s3c/include/plat/watchdog-reset.h
*
* Copyright (c) 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - System define for arch_reset() function
*
* 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 <plat/clock.h>
#include <plat/regs-watchdog.h>
#include <mach/map.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/delay.h>
static inline void arch_wdt_reset(void)
{
printk("arch_reset: attempting watchdog reset\n");
__raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */
if (!IS_ERR(s3c2410_wdtclk))
clk_enable(s3c2410_wdtclk);
/* put initial values into count and data */
__raw_writel(0x80, S3C2410_WTCNT);
__raw_writel(0x80, S3C2410_WTDAT);
/* set the watchdog to go and reset... */
__raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
/* wait for reset to assert... */
mdelay(500);
printk(KERN_ERR "Watchdog reset failed to assert reset\n");
/* delay to allow the serial port to show the message */
mdelay(50);
}

View File

@@ -0,0 +1,160 @@
/* linux/arch/arm/plat-s3c/init.c
*
* Copyright (c) 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* S3C series CPU initialisation
*
* 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/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <mach/hardware.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/clock.h>
#include <plat/regs-serial.h>
static struct cpu_table *cpu;
static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode,
struct cpu_table *tab,
unsigned int count)
{
for (; count != 0; count--, tab++) {
if ((idcode & tab->idmask) == (tab->idcode & tab->idmask))
return tab;
}
return NULL;
}
void __init s3c_init_cpu(unsigned long idcode,
struct cpu_table *cputab, unsigned int cputab_size)
{
cpu = s3c_lookup_cpu(idcode, cputab, cputab_size);
if (cpu == NULL) {
printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode);
panic("Unknown S3C24XX CPU");
}
printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
if (cpu->map_io == NULL || cpu->init == NULL) {
printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
panic("Unsupported Samsung CPU");
}
cpu->map_io();
}
/* s3c24xx_init_clocks
*
* Initialise the clock subsystem and associated information from the
* given master crystal value.
*
* xtal = 0 -> use default PLL crystal value (normally 12MHz)
* != 0 -> PLL crystal value in Hz
*/
void __init s3c24xx_init_clocks(int xtal)
{
if (xtal == 0)
xtal = 12*1000*1000;
if (cpu == NULL)
panic("s3c24xx_init_clocks: no cpu setup?\n");
if (cpu->init_clocks == NULL)
panic("s3c24xx_init_clocks: cpu has no clock init\n");
else
(cpu->init_clocks)(xtal);
}
/* uart management */
static int nr_uarts __initdata = 0;
static struct s3c2410_uartcfg uart_cfgs[CONFIG_SERIAL_SAMSUNG_UARTS];
/* s3c24xx_init_uartdevs
*
* copy the specified platform data and configuration into our central
* set of devices, before the data is thrown away after the init process.
*
* This also fills in the array passed to the serial driver for the
* early initialisation of the console.
*/
void __init s3c24xx_init_uartdevs(char *name,
struct s3c24xx_uart_resources *res,
struct s3c2410_uartcfg *cfg, int no)
{
struct platform_device *platdev;
struct s3c2410_uartcfg *cfgptr = uart_cfgs;
struct s3c24xx_uart_resources *resp;
int uart;
memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);
for (uart = 0; uart < no; uart++, cfg++, cfgptr++) {
platdev = s3c24xx_uart_src[cfgptr->hwport];
resp = res + cfgptr->hwport;
s3c24xx_uart_devs[uart] = platdev;
platdev->name = name;
platdev->resource = resp->resources;
platdev->num_resources = resp->nr_resources;
platdev->dev.platform_data = cfgptr;
}
nr_uarts = no;
}
void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{
if (cpu == NULL)
return;
if (cpu->init_uarts == NULL) {
printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n");
} else
(cpu->init_uarts)(cfg, no);
}
static int __init s3c_arch_init(void)
{
int ret;
// do the correct init for cpu
if (cpu == NULL)
panic("s3c_arch_init: NULL cpu\n");
ret = (cpu->init)();
if (ret != 0)
return ret;
ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts);
return ret;
}
arch_initcall(s3c_arch_init);

View File

@@ -0,0 +1,98 @@
/* arch/arm/plat-samsung/irq-vic-timer.c
* originally part of arch/arm/plat-s3c64xx/irq.c
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* S3C64XX - Interrupt handling
*
* 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/interrupt.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/io.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include <plat/cpu.h>
#include <plat/irq-vic-timer.h>
#include <plat/regs-timer.h>
static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc)
{
struct irq_chip *chip = irq_get_chip(irq);
chained_irq_enter(chip, desc);
generic_handle_irq((int)desc->irq_data.handler_data);
chained_irq_exit(chip, desc);
}
/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
static void s3c_irq_timer_ack(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
u32 mask = (1 << 5) << (d->irq - gc->irq_base);
irq_reg_writel(mask | gc->mask_cache, gc->reg_base);
}
/**
* s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\
* @num: Number of timers to initialize
* @timer_irq: Base IRQ number to be used for the timers.
*
* Register the necessary IRQ chaining and support for the timer IRQs
* chained of the VIC.
*/
void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq)
{
unsigned int pirq[5] = { IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
IRQ_TIMER3_VIC, IRQ_TIMER4_VIC };
struct irq_chip_generic *s3c_tgc;
struct irq_chip_type *ct;
unsigned int i;
#ifdef CONFIG_ARCH_EXYNOS
if (soc_is_exynos5250()) {
pirq[0] = EXYNOS5_IRQ_TIMER0_VIC;
pirq[1] = EXYNOS5_IRQ_TIMER1_VIC;
pirq[2] = EXYNOS5_IRQ_TIMER2_VIC;
pirq[3] = EXYNOS5_IRQ_TIMER3_VIC;
pirq[4] = EXYNOS5_IRQ_TIMER4_VIC;
} else {
pirq[0] = EXYNOS4_IRQ_TIMER0_VIC;
pirq[1] = EXYNOS4_IRQ_TIMER1_VIC;
pirq[2] = EXYNOS4_IRQ_TIMER2_VIC;
pirq[3] = EXYNOS4_IRQ_TIMER3_VIC;
pirq[4] = EXYNOS4_IRQ_TIMER4_VIC;
}
#endif
s3c_tgc = irq_alloc_generic_chip("s3c-timer", 1, timer_irq,
S3C64XX_TINT_CSTAT, handle_level_irq);
if (!s3c_tgc) {
pr_err("%s: irq_alloc_generic_chip for IRQ %d failed\n",
__func__, timer_irq);
return;
}
ct = s3c_tgc->chip_types;
ct->chip.irq_mask = irq_gc_mask_clr_bit;
ct->chip.irq_unmask = irq_gc_mask_set_bit;
ct->chip.irq_ack = s3c_irq_timer_ack;
irq_setup_generic_chip(s3c_tgc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
/* Clear the upper bits of the mask_cache*/
s3c_tgc->mask_cache &= 0x1f;
for (i = 0; i < num; i++, timer_irq++) {
irq_set_chained_handler(pirq[i], s3c_irq_demux_vic_timer);
irq_set_handler_data(pirq[i], (void *)timer_irq);
}
}

View File

@@ -0,0 +1,60 @@
/* linux/arch/arm/plat-samsung/platformdata.c
*
* Copyright 2010 Ben Dooks <ben-linux <at> fluff.org>
*
* Helper for platform data setting
*
* 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/slab.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <plat/devs.h>
#include <plat/sdhci.h>
void __init *s3c_set_platdata(void *pd, size_t pdsize,
struct platform_device *pdev)
{
void *npd;
if (!pd) {
/* too early to use dev_name(), may not be registered */
printk(KERN_ERR "%s: no platform data supplied\n", pdev->name);
return NULL;
}
npd = kmemdup(pd, pdsize, GFP_KERNEL);
if (!npd) {
printk(KERN_ERR "%s: cannot clone platform data\n", pdev->name);
return NULL;
}
pdev->dev.platform_data = npd;
return npd;
}
void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
struct s3c_sdhci_platdata *set)
{
set->cd_type = pd->cd_type;
set->ext_cd_init = pd->ext_cd_init;
set->ext_cd_cleanup = pd->ext_cd_cleanup;
set->ext_cd_gpio = pd->ext_cd_gpio;
set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
if (pd->max_width)
set->max_width = pd->max_width;
if (pd->cfg_gpio)
set->cfg_gpio = pd->cfg_gpio;
if (pd->host_caps)
set->host_caps |= pd->host_caps;
if (pd->host_caps2)
set->host_caps2 |= pd->host_caps2;
if (pd->pm_caps)
set->pm_caps |= pd->pm_caps;
}

View File

@@ -0,0 +1,237 @@
/* linux/arch/arm/plat-s3c/pm-check.c
* originally in linux/arch/arm/plat-s3c24xx/pm.c
*
* Copyright (c) 2004-2008 Simtec Electronics
* http://armlinux.simtec.co.uk
* Ben Dooks <ben@simtec.co.uk>
*
* S3C Power Mangament - suspend/resume memory corruptiuon check.
*
* 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/suspend.h>
#include <linux/init.h>
#include <linux/crc32.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <plat/pm.h>
#if CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE < 1
#error CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE must be a positive non-zero value
#endif
/* suspend checking code...
*
* this next area does a set of crc checks over all the installed
* memory, so the system can verify if the resume was ok.
*
* CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
* increasing it will mean that the area corrupted will be less easy to spot,
* and reducing the size will cause the CRC save area to grow
*/
#define CHECK_CHUNKSIZE (CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE * 1024)
static u32 crc_size; /* size needed for the crc block */
static u32 *crcs; /* allocated over suspend/resume */
typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
/* s3c_pm_run_res
*
* go through the given resource list, and look for system ram
*/
static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
{
while (ptr != NULL) {
if (ptr->child != NULL)
s3c_pm_run_res(ptr->child, fn, arg);
if ((ptr->flags & IORESOURCE_MEM) &&
strcmp(ptr->name, "System RAM") == 0) {
S3C_PMDBG("Found system RAM at %08lx..%08lx\n",
(unsigned long)ptr->start,
(unsigned long)ptr->end);
arg = (fn)(ptr, arg);
}
ptr = ptr->sibling;
}
}
static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg)
{
s3c_pm_run_res(&iomem_resource, fn, arg);
}
static u32 *s3c_pm_countram(struct resource *res, u32 *val)
{
u32 size = (u32)resource_size(res);
size += CHECK_CHUNKSIZE-1;
size /= CHECK_CHUNKSIZE;
S3C_PMDBG("Area %08lx..%08lx, %d blocks\n",
(unsigned long)res->start, (unsigned long)res->end, size);
*val += size * sizeof(u32);
return val;
}
/* s3c_pm_prepare_check
*
* prepare the necessary information for creating the CRCs. This
* must be done before the final save, as it will require memory
* allocating, and thus touching bits of the kernel we do not
* know about.
*/
void s3c_pm_check_prepare(void)
{
crc_size = 0;
s3c_pm_run_sysram(s3c_pm_countram, &crc_size);
S3C_PMDBG("s3c_pm_prepare_check: %u checks needed\n", crc_size);
crcs = kmalloc(crc_size+4, GFP_KERNEL);
if (crcs == NULL)
printk(KERN_ERR "Cannot allocated CRC save area\n");
}
static u32 *s3c_pm_makecheck(struct resource *res, u32 *val)
{
unsigned long addr, left;
for (addr = res->start; addr < res->end;
addr += CHECK_CHUNKSIZE) {
left = res->end - addr;
if (left > CHECK_CHUNKSIZE)
left = CHECK_CHUNKSIZE;
*val = crc32_le(~0, phys_to_virt(addr), left);
val++;
}
return val;
}
/* s3c_pm_check_store
*
* compute the CRC values for the memory blocks before the final
* sleep.
*/
void s3c_pm_check_store(void)
{
if (crcs != NULL)
s3c_pm_run_sysram(s3c_pm_makecheck, crcs);
}
/* in_region
*
* return TRUE if the area defined by ptr..ptr+size contains the
* what..what+whatsz
*/
static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
{
if ((what+whatsz) < ptr)
return 0;
if (what > (ptr+size))
return 0;
return 1;
}
/**
* s3c_pm_runcheck() - helper to check a resource on restore.
* @res: The resource to check
* @vak: Pointer to list of CRC32 values to check.
*
* Called from the s3c_pm_check_restore() via s3c_pm_run_sysram(), this
* function runs the given memory resource checking it against the stored
* CRC to ensure that memory is restored. The function tries to skip as
* many of the areas used during the suspend process.
*/
static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
{
unsigned long addr;
unsigned long left;
void *stkpage;
void *ptr;
u32 calc;
stkpage = (void *)((u32)&calc & ~PAGE_MASK);
for (addr = res->start; addr < res->end;
addr += CHECK_CHUNKSIZE) {
left = res->end - addr;
if (left > CHECK_CHUNKSIZE)
left = CHECK_CHUNKSIZE;
ptr = phys_to_virt(addr);
if (in_region(ptr, left, stkpage, 4096)) {
S3C_PMDBG("skipping %08lx, has stack in\n", addr);
goto skip_check;
}
if (in_region(ptr, left, crcs, crc_size)) {
S3C_PMDBG("skipping %08lx, has crc block in\n", addr);
goto skip_check;
}
/* calculate and check the checksum */
calc = crc32_le(~0, ptr, left);
if (calc != *val) {
printk(KERN_ERR "Restore CRC error at "
"%08lx (%08x vs %08x)\n", addr, calc, *val);
S3C_PMDBG("Restore CRC error at %08lx (%08x vs %08x)\n",
addr, calc, *val);
}
skip_check:
val++;
}
return val;
}
/**
* s3c_pm_check_restore() - memory check called on resume
*
* check the CRCs after the restore event and free the memory used
* to hold them
*/
void s3c_pm_check_restore(void)
{
if (crcs != NULL)
s3c_pm_run_sysram(s3c_pm_runcheck, crcs);
}
/**
* s3c_pm_check_cleanup() - free memory resources
*
* Free the resources that where allocated by the suspend
* memory check code. We do this separately from the
* s3c_pm_check_restore() function as we cannot call any
* functions that might sleep during that resume.
*/
void s3c_pm_check_cleanup(void)
{
kfree(crcs);
crcs = NULL;
}

View File

@@ -0,0 +1,384 @@
/* linux/arch/arm/plat-s3c/pm-gpio.c
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* S3C series GPIO PM code
*
* 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/device.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <plat/gpio-core.h>
#include <plat/pm.h>
/* PM GPIO helpers */
#define OFFS_CON (0x00)
#define OFFS_DAT (0x04)
#define OFFS_UP (0x08)
static void samsung_gpio_pm_1bit_save(struct samsung_gpio_chip *chip)
{
chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
}
static void samsung_gpio_pm_1bit_resume(struct samsung_gpio_chip *chip)
{
void __iomem *base = chip->base;
u32 old_gpcon = __raw_readl(base + OFFS_CON);
u32 old_gpdat = __raw_readl(base + OFFS_DAT);
u32 gps_gpcon = chip->pm_save[0];
u32 gps_gpdat = chip->pm_save[1];
u32 gpcon;
/* GPACON only has one bit per control / data and no PULLUPs.
* GPACON[x] = 0 => Output, 1 => SFN */
/* first set all SFN bits to SFN */
gpcon = old_gpcon | gps_gpcon;
__raw_writel(gpcon, base + OFFS_CON);
/* now set all the other bits */
__raw_writel(gps_gpdat, base + OFFS_DAT);
__raw_writel(gps_gpcon, base + OFFS_CON);
S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
}
struct samsung_gpio_pm samsung_gpio_pm_1bit = {
.save = samsung_gpio_pm_1bit_save,
.resume = samsung_gpio_pm_1bit_resume,
};
static void samsung_gpio_pm_2bit_save(struct samsung_gpio_chip *chip)
{
chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
}
/* Test whether the given masked+shifted bits of an GPIO configuration
* are one of the SFN (special function) modes. */
static inline int is_sfn(unsigned long con)
{
return con >= 2;
}
/* Test if the given masked+shifted GPIO configuration is an input */
static inline int is_in(unsigned long con)
{
return con == 0;
}
/* Test if the given masked+shifted GPIO configuration is an output */
static inline int is_out(unsigned long con)
{
return con == 1;
}
/**
* samsung_gpio_pm_2bit_resume() - restore the given GPIO bank
* @chip: The chip information to resume.
*
* Restore one of the GPIO banks that was saved during suspend. This is
* not as simple as once thought, due to the possibility of glitches
* from the order that the CON and DAT registers are set in.
*
* The three states the pin can be are {IN,OUT,SFN} which gives us 9
* combinations of changes to check. Three of these, if the pin stays
* in the same configuration can be discounted. This leaves us with
* the following:
*
* { IN => OUT } Change DAT first
* { IN => SFN } Change CON first
* { OUT => SFN } Change CON first, so new data will not glitch
* { OUT => IN } Change CON first, so new data will not glitch
* { SFN => IN } Change CON first
* { SFN => OUT } Change DAT first, so new data will not glitch [1]
*
* We do not currently deal with the UP registers as these control
* weak resistors, so a small delay in change should not need to bring
* these into the calculations.
*
* [1] this assumes that writing to a pin DAT whilst in SFN will set the
* state for when it is next output.
*/
static void samsung_gpio_pm_2bit_resume(struct samsung_gpio_chip *chip)
{
void __iomem *base = chip->base;
u32 old_gpcon = __raw_readl(base + OFFS_CON);
u32 old_gpdat = __raw_readl(base + OFFS_DAT);
u32 gps_gpcon = chip->pm_save[0];
u32 gps_gpdat = chip->pm_save[1];
u32 gpcon, old, new, mask;
u32 change_mask = 0x0;
int nr;
/* restore GPIO pull-up settings */
__raw_writel(chip->pm_save[2], base + OFFS_UP);
/* Create a change_mask of all the items that need to have
* their CON value changed before their DAT value, so that
* we minimise the work between the two settings.
*/
for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
old = (old_gpcon & mask) >> nr;
new = (gps_gpcon & mask) >> nr;
/* If there is no change, then skip */
if (old == new)
continue;
/* If both are special function, then skip */
if (is_sfn(old) && is_sfn(new))
continue;
/* Change is IN => OUT, do not change now */
if (is_in(old) && is_out(new))
continue;
/* Change is SFN => OUT, do not change now */
if (is_sfn(old) && is_out(new))
continue;
/* We should now be at the case of IN=>SFN,
* OUT=>SFN, OUT=>IN, SFN=>IN. */
change_mask |= mask;
}
/* Write the new CON settings */
gpcon = old_gpcon & ~change_mask;
gpcon |= gps_gpcon & change_mask;
__raw_writel(gpcon, base + OFFS_CON);
/* Now change any items that require DAT,CON */
__raw_writel(gps_gpdat, base + OFFS_DAT);
__raw_writel(gps_gpcon, base + OFFS_CON);
S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
}
struct samsung_gpio_pm samsung_gpio_pm_2bit = {
.save = samsung_gpio_pm_2bit_save,
.resume = samsung_gpio_pm_2bit_resume,
};
#if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
static void samsung_gpio_pm_4bit_save(struct samsung_gpio_chip *chip)
{
chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
if (chip->chip.ngpio > 8)
chip->pm_save[0] = __raw_readl(chip->base - 4);
}
static u32 samsung_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
{
u32 old, new, mask;
u32 change_mask = 0x0;
int nr;
for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
old = (old_gpcon & mask) >> nr;
new = (gps_gpcon & mask) >> nr;
/* If there is no change, then skip */
if (old == new)
continue;
/* If both are special function, then skip */
if (is_sfn(old) && is_sfn(new))
continue;
/* Change is IN => OUT, do not change now */
if (is_in(old) && is_out(new))
continue;
/* Change is SFN => OUT, do not change now */
if (is_sfn(old) && is_out(new))
continue;
/* We should now be at the case of IN=>SFN,
* OUT=>SFN, OUT=>IN, SFN=>IN. */
change_mask |= mask;
}
return change_mask;
}
static void samsung_gpio_pm_4bit_con(struct samsung_gpio_chip *chip, int index)
{
void __iomem *con = chip->base + (index * 4);
u32 old_gpcon = __raw_readl(con);
u32 gps_gpcon = chip->pm_save[index + 1];
u32 gpcon, mask;
mask = samsung_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
gpcon = old_gpcon & ~mask;
gpcon |= gps_gpcon & mask;
__raw_writel(gpcon, con);
}
static void samsung_gpio_pm_4bit_resume(struct samsung_gpio_chip *chip)
{
void __iomem *base = chip->base;
u32 old_gpcon[2];
u32 old_gpdat = __raw_readl(base + OFFS_DAT);
u32 gps_gpdat = chip->pm_save[2];
/* First, modify the CON settings */
old_gpcon[0] = 0;
old_gpcon[1] = __raw_readl(base + OFFS_CON);
samsung_gpio_pm_4bit_con(chip, 0);
if (chip->chip.ngpio > 8) {
old_gpcon[0] = __raw_readl(base - 4);
samsung_gpio_pm_4bit_con(chip, -1);
}
/* Now change the configurations that require DAT,CON */
__raw_writel(chip->pm_save[2], base + OFFS_DAT);
__raw_writel(chip->pm_save[1], base + OFFS_CON);
if (chip->chip.ngpio > 8)
__raw_writel(chip->pm_save[0], base - 4);
__raw_writel(chip->pm_save[2], base + OFFS_DAT);
__raw_writel(chip->pm_save[3], base + OFFS_UP);
if (chip->chip.ngpio > 8) {
S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
chip->chip.label, old_gpcon[0], old_gpcon[1],
__raw_readl(base - 4),
__raw_readl(base + OFFS_CON),
old_gpdat, gps_gpdat);
} else
S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
chip->chip.label, old_gpcon[1],
__raw_readl(base + OFFS_CON),
old_gpdat, gps_gpdat);
}
struct samsung_gpio_pm samsung_gpio_pm_4bit = {
.save = samsung_gpio_pm_4bit_save,
.resume = samsung_gpio_pm_4bit_resume,
};
#endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
/**
* samsung_pm_save_gpio() - save gpio chip data for suspend
* @ourchip: The chip for suspend.
*/
static void samsung_pm_save_gpio(struct samsung_gpio_chip *ourchip)
{
struct samsung_gpio_pm *pm = ourchip->pm;
if (pm == NULL || pm->save == NULL)
S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
else
pm->save(ourchip);
}
/**
* samsung_pm_save_gpios() - Save the state of the GPIO banks.
*
* For all the GPIO banks, save the state of each one ready for going
* into a suspend mode.
*/
void samsung_pm_save_gpios(void)
{
struct samsung_gpio_chip *ourchip;
unsigned int gpio_nr;
for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
ourchip = samsung_gpiolib_getchip(gpio_nr);
if (!ourchip) {
gpio_nr++;
continue;
}
samsung_pm_save_gpio(ourchip);
S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
ourchip->chip.label,
ourchip->pm_save[0],
ourchip->pm_save[1],
ourchip->pm_save[2],
ourchip->pm_save[3]);
gpio_nr += ourchip->chip.ngpio;
gpio_nr += CONFIG_S3C_GPIO_SPACE;
}
}
/**
* samsung_pm_resume_gpio() - restore gpio chip data after suspend
* @ourchip: The suspended chip.
*/
static void samsung_pm_resume_gpio(struct samsung_gpio_chip *ourchip)
{
struct samsung_gpio_pm *pm = ourchip->pm;
if (pm == NULL || pm->resume == NULL)
S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
else
pm->resume(ourchip);
}
void samsung_pm_restore_gpios(void)
{
struct samsung_gpio_chip *ourchip;
unsigned int gpio_nr;
for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
ourchip = samsung_gpiolib_getchip(gpio_nr);
if (!ourchip) {
gpio_nr++;
continue;
}
samsung_pm_resume_gpio(ourchip);
gpio_nr += ourchip->chip.ngpio;
gpio_nr += CONFIG_S3C_GPIO_SPACE;
}
}

376
arch/arm/plat-samsung/pm.c Normal file
View File

@@ -0,0 +1,376 @@
/* linux/arch/arm/plat-s3c/pm.c
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2004-2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* S3C common power management (suspend to ram) support.
*
* 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/init.h>
#include <linux/suspend.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/serial_core.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
#include <asm/suspend.h>
#include <mach/hardware.h>
#include <mach/map.h>
#include <plat/regs-serial.h>
#include <mach/regs-clock.h>
#include <mach/regs-irq.h>
#include <mach/irqs.h>
#include <asm/irq.h>
#include <plat/pm.h>
#include <mach/pm-core.h>
/* for external use */
unsigned long s3c_pm_flags;
/* Debug code:
*
* This code supports debug output to the low level UARTs for use on
* resume before the console layer is available.
*/
#ifdef CONFIG_SAMSUNG_PM_DEBUG
extern void printascii(const char *);
void s3c_pm_dbg(const char *fmt, ...)
{
va_list va;
char buff[256];
va_start(va, fmt);
vsnprintf(buff, sizeof(buff), fmt, va);
va_end(va);
printascii(buff);
}
static inline void s3c_pm_debug_init(void)
{
/* restart uart clocks so we can use them to output */
s3c_pm_debug_init_uart();
}
#else
#define s3c_pm_debug_init() do { } while(0)
#endif /* CONFIG_SAMSUNG_PM_DEBUG */
/* Save the UART configurations if we are configured for debug. */
unsigned char pm_uart_udivslot;
#ifdef CONFIG_SAMSUNG_PM_DEBUG
static struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
{
void __iomem *regs = S3C_VA_UARTx(uart);
save->ulcon = __raw_readl(regs + S3C2410_ULCON);
save->ucon = __raw_readl(regs + S3C2410_UCON);
save->ufcon = __raw_readl(regs + S3C2410_UFCON);
save->umcon = __raw_readl(regs + S3C2410_UMCON);
save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
if (pm_uart_udivslot)
save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
}
static void s3c_pm_save_uarts(void)
{
struct pm_uart_save *save = uart_save;
unsigned int uart;
for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
s3c_pm_save_uart(uart, save);
}
static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
{
void __iomem *regs = S3C_VA_UARTx(uart);
s3c_pm_arch_update_uart(regs, save);
__raw_writel(save->ulcon, regs + S3C2410_ULCON);
__raw_writel(save->ucon, regs + S3C2410_UCON);
__raw_writel(save->ufcon, regs + S3C2410_UFCON);
__raw_writel(save->umcon, regs + S3C2410_UMCON);
__raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
if (pm_uart_udivslot)
__raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
}
static void s3c_pm_restore_uarts(void)
{
struct pm_uart_save *save = uart_save;
unsigned int uart;
for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
s3c_pm_restore_uart(uart, save);
}
#else
static void s3c_pm_save_uarts(void) { }
static void s3c_pm_restore_uarts(void) { }
#endif
/* The IRQ ext-int code goes here, it is too small to currently bother
* with its own file. */
unsigned long s3c_irqwake_intmask = 0xffffffffL;
unsigned long s3c_irqwake_eintmask = 0xffffffffL;
int s3c_irqext_wake(struct irq_data *data, unsigned int state)
{
unsigned long bit = 1L << IRQ_EINT_BIT(data->irq);
if (!(s3c_irqwake_eintallow & bit))
return -ENOENT;
printk(KERN_INFO "wake %s for irq %d\n",
state ? "enabled" : "disabled", data->irq);
if (!state)
s3c_irqwake_eintmask |= bit;
else
s3c_irqwake_eintmask &= ~bit;
return 0;
}
/* helper functions to save and restore register state */
/**
* s3c_pm_do_save() - save a set of registers for restoration on resume.
* @ptr: Pointer to an array of registers.
* @count: Size of the ptr array.
*
* Run through the list of registers given, saving their contents in the
* array for later restoration when we wakeup.
*/
void s3c_pm_do_save(struct sleep_save *ptr, int count)
{
for (; count > 0; count--, ptr++) {
ptr->val = __raw_readl(ptr->reg);
S3C_PMDBG("saved %p value %08lx\n", ptr->reg, ptr->val);
}
}
/**
* s3c_pm_do_restore() - restore register values from the save list.
* @ptr: Pointer to an array of registers.
* @count: Size of the ptr array.
*
* Restore the register values saved from s3c_pm_do_save().
*
* Note, we do not use S3C_PMDBG() in here, as the system may not have
* restore the UARTs state yet
*/
void s3c_pm_do_restore(struct sleep_save *ptr, int count)
{
for (; count > 0; count--, ptr++) {
printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
ptr->reg, ptr->val, __raw_readl(ptr->reg));
__raw_writel(ptr->val, ptr->reg);
}
}
/**
* s3c_pm_do_restore_core() - early restore register values from save list.
*
* This is similar to s3c_pm_do_restore() except we try and minimise the
* side effects of the function in case registers that hardware might need
* to work has been restored.
*
* WARNING: Do not put any debug in here that may effect memory or use
* peripherals, as things may be changing!
*/
void s3c_pm_do_restore_core(struct sleep_save *ptr, int count)
{
for (; count > 0; count--, ptr++)
__raw_writel(ptr->val, ptr->reg);
}
/* s3c2410_pm_show_resume_irqs
*
* print any IRQs asserted at resume time (ie, we woke from)
*/
static void __maybe_unused s3c_pm_show_resume_irqs(int start,
unsigned long which,
unsigned long mask)
{
int i;
which &= ~mask;
for (i = 0; i <= 31; i++) {
if (which & (1L<<i)) {
S3C_PMDBG("IRQ %d asserted at resume\n", start+i);
}
}
}
void (*pm_cpu_prep)(void);
int (*pm_cpu_sleep)(unsigned long);
#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
/* s3c_pm_enter
*
* central control for sleep/resume process
*/
static int s3c_pm_enter(suspend_state_t state)
{
int ret;
/* ensure the debug is initialised (if enabled) */
s3c_pm_debug_init();
S3C_PMDBG("%s(%d)\n", __func__, state);
if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__);
return -EINVAL;
}
/* check if we have anything to wake-up with... bad things seem
* to happen if you suspend with no wakeup (system will often
* require a full power-cycle)
*/
if (!of_have_populated_dt() &&
!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
!any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
printk(KERN_ERR "%s: No wake-up sources!\n", __func__);
printk(KERN_ERR "%s: Aborting sleep\n", __func__);
return -EINVAL;
}
/* save all necessary core registers not covered by the drivers */
if (!of_have_populated_dt()) {
samsung_pm_save_gpios();
samsung_pm_saved_gpios();
}
s3c_pm_save_uarts();
s3c_pm_save_core();
/* set the irq configuration for wake */
s3c_pm_configure_extint();
S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n",
s3c_irqwake_intmask, s3c_irqwake_eintmask);
s3c_pm_arch_prepare_irqs();
/* call cpu specific preparation */
pm_cpu_prep();
/* flush cache back to ram */
flush_cache_all();
s3c_pm_check_store();
/* send the cpu to sleep... */
s3c_pm_arch_stop_clocks();
/* this will also act as our return point from when
* we resume as it saves its own register state and restores it
* during the resume. */
ret = cpu_suspend(0, pm_cpu_sleep);
if (ret)
return ret;
/* restore the system state */
s3c_pm_restore_core();
s3c_pm_restore_uarts();
if (!of_have_populated_dt()) {
samsung_pm_restore_gpios();
s3c_pm_restored_gpios();
}
s3c_pm_debug_init();
/* check what irq (if any) restored the system */
s3c_pm_arch_show_resume_irqs();
S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
/* LEDs should now be 1110 */
s3c_pm_debug_smdkled(1 << 1, 0);
s3c_pm_check_restore();
/* ok, let's return from sleep */
S3C_PMDBG("S3C PM Resume (post-restore)\n");
return 0;
}
static int s3c_pm_prepare(void)
{
/* prepare check area if configured */
s3c_pm_check_prepare();
return 0;
}
static void s3c_pm_finish(void)
{
s3c_pm_check_cleanup();
}
static const struct platform_suspend_ops s3c_pm_ops = {
.enter = s3c_pm_enter,
.prepare = s3c_pm_prepare,
.finish = s3c_pm_finish,
.valid = suspend_valid_only_mem,
};
/* s3c_pm_init
*
* Attach the power management functions. This should be called
* from the board specific initialisation if the board supports
* it.
*/
int __init s3c_pm_init(void)
{
printk("S3C Power Management, Copyright 2004 Simtec Electronics\n");
suspend_set_ops(&s3c_pm_ops);
return 0;
}

View File

@@ -0,0 +1,474 @@
/* linux/arch/arm/plat-s3c24xx/pwm-clock.c
*
* Copyright (c) 2007 Simtec Electronics
* Copyright (c) 2007, 2008 Ben Dooks
* Ben Dooks <ben-linux@fluff.org>
*
* 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.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/log2.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/map.h>
#include <asm/irq.h>
#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/regs-timer.h>
#include <plat/pwm-clock.h>
/* Each of the timers 0 through 5 go through the following
* clock tree, with the inputs depending on the timers.
*
* pclk ---- [ prescaler 0 ] -+---> timer 0
* +---> timer 1
*
* pclk ---- [ prescaler 1 ] -+---> timer 2
* +---> timer 3
* \---> timer 4
*
* Which are fed into the timers as so:
*
* prescaled 0 ---- [ div 2,4,8,16 ] ---\
* [mux] -> timer 0
* tclk 0 ------------------------------/
*
* prescaled 0 ---- [ div 2,4,8,16 ] ---\
* [mux] -> timer 1
* tclk 0 ------------------------------/
*
*
* prescaled 1 ---- [ div 2,4,8,16 ] ---\
* [mux] -> timer 2
* tclk 1 ------------------------------/
*
* prescaled 1 ---- [ div 2,4,8,16 ] ---\
* [mux] -> timer 3
* tclk 1 ------------------------------/
*
* prescaled 1 ---- [ div 2,4,8, 16 ] --\
* [mux] -> timer 4
* tclk 1 ------------------------------/
*
* Since the mux and the divider are tied together in the
* same register space, it is impossible to set the parent
* and the rate at the same time. To avoid this, we add an
* intermediate 'prescaled-and-divided' clock to select
* as the parent for the timer input clock called tdiv.
*
* prescaled clk --> pwm-tdiv ---\
* [ mux ] --> timer X
* tclk -------------------------/
*/
static struct clk clk_timer_scaler[];
static unsigned long clk_pwm_scaler_get_rate(struct clk *clk)
{
unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0);
if (clk == &clk_timer_scaler[1]) {
tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK;
tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT;
} else {
tcfg0 &= S3C2410_TCFG_PRESCALER0_MASK;
}
return clk_get_rate(clk->parent) / (tcfg0 + 1);
}
static unsigned long clk_pwm_scaler_round_rate(struct clk *clk,
unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
unsigned long divisor = parent_rate / rate;
if (divisor > 256)
divisor = 256;
else if (divisor < 2)
divisor = 2;
return parent_rate / divisor;
}
static int clk_pwm_scaler_set_rate(struct clk *clk, unsigned long rate)
{
unsigned long round = clk_pwm_scaler_round_rate(clk, rate);
unsigned long tcfg0;
unsigned long divisor;
unsigned long flags;
divisor = clk_get_rate(clk->parent) / round;
divisor--;
local_irq_save(flags);
tcfg0 = __raw_readl(S3C2410_TCFG0);
if (clk == &clk_timer_scaler[1]) {
tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
tcfg0 |= divisor << S3C2410_TCFG_PRESCALER1_SHIFT;
} else {
tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
tcfg0 |= divisor;
}
__raw_writel(tcfg0, S3C2410_TCFG0);
local_irq_restore(flags);
return 0;
}
static struct clk_ops clk_pwm_scaler_ops = {
.get_rate = clk_pwm_scaler_get_rate,
.set_rate = clk_pwm_scaler_set_rate,
.round_rate = clk_pwm_scaler_round_rate,
};
static struct clk clk_timer_scaler[] = {
[0] = {
.name = "pwm-scaler0",
.id = -1,
.ops = &clk_pwm_scaler_ops,
},
[1] = {
.name = "pwm-scaler1",
.id = -1,
.ops = &clk_pwm_scaler_ops,
},
};
static struct clk clk_timer_tclk[] = {
[0] = {
.name = "pwm-tclk0",
.id = -1,
},
[1] = {
.name = "pwm-tclk1",
.id = -1,
},
};
struct pwm_tdiv_clk {
struct clk clk;
unsigned int divisor;
};
static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk)
{
return container_of(clk, struct pwm_tdiv_clk, clk);
}
static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk)
{
unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
unsigned int divisor;
tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
tcfg1 &= S3C2410_TCFG1_MUX_MASK;
if (pwm_cfg_src_is_tclk(tcfg1))
divisor = to_tdiv(clk)->divisor;
else
divisor = tcfg_to_divisor(tcfg1);
return clk_get_rate(clk->parent) / divisor;
}
static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk,
unsigned long rate)
{
unsigned long parent_rate;
unsigned long divisor;
parent_rate = clk_get_rate(clk->parent);
divisor = parent_rate / rate;
if (divisor <= 1 && pwm_tdiv_has_div1())
divisor = 1;
else if (divisor <= 2)
divisor = 2;
else if (divisor <= 4)
divisor = 4;
else if (divisor <= 8)
divisor = 8;
else
divisor = 16;
return parent_rate / divisor;
}
static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk)
{
return pwm_tdiv_div_bits(divclk->divisor);
}
static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk)
{
unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
unsigned long bits = clk_pwm_tdiv_bits(divclk);
unsigned long flags;
unsigned long shift = S3C2410_TCFG1_SHIFT(divclk->clk.id);
local_irq_save(flags);
tcfg1 = __raw_readl(S3C2410_TCFG1);
tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
tcfg1 |= bits << shift;
__raw_writel(tcfg1, S3C2410_TCFG1);
local_irq_restore(flags);
}
static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate)
{
struct pwm_tdiv_clk *divclk = to_tdiv(clk);
unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
unsigned long parent_rate = clk_get_rate(clk->parent);
unsigned long divisor;
tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
tcfg1 &= S3C2410_TCFG1_MUX_MASK;
rate = clk_round_rate(clk, rate);
divisor = parent_rate / rate;
if (divisor > 16)
return -EINVAL;
divclk->divisor = divisor;
/* Update the current MUX settings if we are currently
* selected as the clock source for this clock. */
if (!pwm_cfg_src_is_tclk(tcfg1))
clk_pwm_tdiv_update(divclk);
return 0;
}
static struct clk_ops clk_tdiv_ops = {
.get_rate = clk_pwm_tdiv_get_rate,
.set_rate = clk_pwm_tdiv_set_rate,
.round_rate = clk_pwm_tdiv_round_rate,
};
static struct pwm_tdiv_clk clk_timer_tdiv[] = {
[0] = {
.clk = {
.name = "pwm-tdiv",
.devname = "s3c24xx-pwm.0",
.ops = &clk_tdiv_ops,
.parent = &clk_timer_scaler[0],
},
},
[1] = {
.clk = {
.name = "pwm-tdiv",
.devname = "s3c24xx-pwm.1",
.ops = &clk_tdiv_ops,
.parent = &clk_timer_scaler[0],
}
},
[2] = {
.clk = {
.name = "pwm-tdiv",
.devname = "s3c24xx-pwm.2",
.ops = &clk_tdiv_ops,
.parent = &clk_timer_scaler[1],
},
},
[3] = {
.clk = {
.name = "pwm-tdiv",
.devname = "s3c24xx-pwm.3",
.ops = &clk_tdiv_ops,
.parent = &clk_timer_scaler[1],
},
},
[4] = {
.clk = {
.name = "pwm-tdiv",
.devname = "s3c24xx-pwm.4",
.ops = &clk_tdiv_ops,
.parent = &clk_timer_scaler[1],
},
},
};
static int __init clk_pwm_tdiv_register(unsigned int id)
{
struct pwm_tdiv_clk *divclk = &clk_timer_tdiv[id];
unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
tcfg1 &= S3C2410_TCFG1_MUX_MASK;
divclk->clk.id = id;
divclk->divisor = tcfg_to_divisor(tcfg1);
return s3c24xx_register_clock(&divclk->clk);
}
static inline struct clk *s3c24xx_pwmclk_tclk(unsigned int id)
{
return (id >= 2) ? &clk_timer_tclk[1] : &clk_timer_tclk[0];
}
static inline struct clk *s3c24xx_pwmclk_tdiv(unsigned int id)
{
return &clk_timer_tdiv[id].clk;
}
static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent)
{
unsigned int id = clk->id;
unsigned long tcfg1;
unsigned long flags;
unsigned long bits;
unsigned long shift = S3C2410_TCFG1_SHIFT(id);
unsigned long mux_tclk;
if (soc_is_s3c24xx())
mux_tclk = S3C2410_TCFG1_MUX_TCLK;
else if (soc_is_s5p6440() || soc_is_s5p6450())
mux_tclk = 0;
else
mux_tclk = S3C64XX_TCFG1_MUX_TCLK;
if (parent == s3c24xx_pwmclk_tclk(id))
bits = mux_tclk << shift;
else if (parent == s3c24xx_pwmclk_tdiv(id))
bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift;
else
return -EINVAL;
clk->parent = parent;
local_irq_save(flags);
tcfg1 = __raw_readl(S3C2410_TCFG1);
tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
__raw_writel(tcfg1 | bits, S3C2410_TCFG1);
local_irq_restore(flags);
return 0;
}
static struct clk_ops clk_tin_ops = {
.set_parent = clk_pwm_tin_set_parent,
};
static struct clk clk_tin[] = {
[0] = {
.name = "pwm-tin",
.devname = "s3c24xx-pwm.0",
.id = 0,
.ops = &clk_tin_ops,
},
[1] = {
.name = "pwm-tin",
.devname = "s3c24xx-pwm.1",
.id = 1,
.ops = &clk_tin_ops,
},
[2] = {
.name = "pwm-tin",
.devname = "s3c24xx-pwm.2",
.id = 2,
.ops = &clk_tin_ops,
},
[3] = {
.name = "pwm-tin",
.devname = "s3c24xx-pwm.3",
.id = 3,
.ops = &clk_tin_ops,
},
[4] = {
.name = "pwm-tin",
.devname = "s3c24xx-pwm.4",
.id = 4,
.ops = &clk_tin_ops,
},
};
static __init int clk_pwm_tin_register(struct clk *pwm)
{
unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
unsigned int id = pwm->id;
struct clk *parent;
int ret;
ret = s3c24xx_register_clock(pwm);
if (ret < 0)
return ret;
tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
tcfg1 &= S3C2410_TCFG1_MUX_MASK;
if (pwm_cfg_src_is_tclk(tcfg1))
parent = s3c24xx_pwmclk_tclk(id);
else
parent = s3c24xx_pwmclk_tdiv(id);
return clk_set_parent(pwm, parent);
}
/**
* s3c_pwmclk_init() - initialise pwm clocks
*
* Initialise and register the clocks which provide the inputs for the
* pwm timer blocks.
*
* Note, this call is required by the time core, so must be called after
* the base clocks are added and before any of the initcalls are run.
*/
__init void s3c_pwmclk_init(void)
{
struct clk *clk_timers;
unsigned int clk;
int ret;
clk_timers = clk_get(NULL, "timers");
if (IS_ERR(clk_timers)) {
printk(KERN_ERR "%s: no parent clock\n", __func__);
return;
}
for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++)
clk_timer_scaler[clk].parent = clk_timers;
s3c_register_clocks(clk_timer_scaler, ARRAY_SIZE(clk_timer_scaler));
s3c_register_clocks(clk_timer_tclk, ARRAY_SIZE(clk_timer_tclk));
for (clk = 0; clk < ARRAY_SIZE(clk_timer_tdiv); clk++) {
ret = clk_pwm_tdiv_register(clk);
if (ret < 0) {
printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk);
return;
}
}
for (clk = 0; clk < ARRAY_SIZE(clk_tin); clk++) {
ret = clk_pwm_tin_register(&clk_tin[clk]);
if (ret < 0) {
printk(KERN_ERR "error adding pwm%d tin clock\n", clk);
return;
}
}
}

View File

@@ -0,0 +1,137 @@
/* linux/arch/arm/plat-samsung/s3c-dma-ops.c
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung S3C-DMA Operations
*
* 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/errno.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/export.h>
#include <mach/dma.h>
struct cb_data {
void (*fp) (void *);
void *fp_param;
unsigned ch;
struct list_head node;
};
static LIST_HEAD(dma_list);
static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
int size, enum s3c2410_dma_buffresult res)
{
struct cb_data *data = param;
data->fp(data->fp_param);
}
static unsigned s3c_dma_request(enum dma_ch dma_ch,
struct samsung_dma_req *param,
struct device *dev, char *ch_name)
{
struct cb_data *data;
if (s3c2410_dma_request(dma_ch, param->client, NULL) < 0) {
s3c2410_dma_free(dma_ch, param->client);
return 0;
}
if (param->cap == DMA_CYCLIC)
s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
data->ch = dma_ch;
list_add_tail(&data->node, &dma_list);
return (unsigned)dma_ch;
}
static int s3c_dma_release(unsigned ch, void *param)
{
struct cb_data *data;
list_for_each_entry(data, &dma_list, node)
if (data->ch == ch)
break;
list_del(&data->node);
s3c2410_dma_free(ch, param);
kfree(data);
return 0;
}
static int s3c_dma_config(unsigned ch, struct samsung_dma_config *param)
{
s3c2410_dma_devconfig(ch, param->direction, param->fifo);
s3c2410_dma_config(ch, param->width);
return 0;
}
static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param)
{
struct cb_data *data;
int len = (param->cap == DMA_CYCLIC) ? param->period : param->len;
list_for_each_entry(data, &dma_list, node)
if (data->ch == ch)
break;
if (!data->fp) {
s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
data->fp = param->fp;
data->fp_param = param->fp_param;
}
s3c2410_dma_enqueue(ch, (void *)data, param->buf, len);
return 0;
}
static inline int s3c_dma_trigger(unsigned ch)
{
return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
}
static inline int s3c_dma_started(unsigned ch)
{
return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
}
static inline int s3c_dma_flush(unsigned ch)
{
return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
}
static inline int s3c_dma_stop(unsigned ch)
{
return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
}
static struct samsung_dma_ops s3c_dma_ops = {
.request = s3c_dma_request,
.release = s3c_dma_release,
.config = s3c_dma_config,
.prepare = s3c_dma_prepare,
.trigger = s3c_dma_trigger,
.started = s3c_dma_started,
.flush = s3c_dma_flush,
.stop = s3c_dma_stop,
};
void *s3c_dma_get_ops(void)
{
return &s3c_dma_ops;
}
EXPORT_SYMBOL(s3c_dma_get_ops);

View File

@@ -0,0 +1,294 @@
/*
* Copyright 2009 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S5P - Common clock support
*
* 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/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
#include <asm/div64.h>
#include <mach/regs-clock.h>
#include <plat/clock.h>
#include <plat/clock-clksrc.h>
#include <plat/s5p-clock.h>
/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
* clk_ext_xtal_mux.
*/
struct clk clk_ext_xtal_mux = {
.name = "ext_xtal",
.id = -1,
};
struct clk clk_xusbxti = {
.name = "xusbxti",
.id = -1,
.rate = 24000000,
};
struct clk s5p_clk_27m = {
.name = "clk_27m",
.id = -1,
.rate = 27000000,
};
/* 48MHz USB Phy clock output */
struct clk clk_48m = {
.name = "clk_48m",
.id = -1,
.rate = 48000000,
};
/* APLL clock output
* No need .ctrlbit, this is always on
*/
struct clk clk_fout_apll = {
.name = "fout_apll",
.id = -1,
};
/* BPLL clock output */
struct clk clk_fout_bpll = {
.name = "fout_bpll",
.id = -1,
};
struct clk clk_fout_bpll_div2 = {
.name = "fout_bpll_div2",
.id = -1,
};
/* CPLL clock output */
struct clk clk_fout_cpll = {
.name = "fout_cpll",
.id = -1,
};
/* MPLL clock output
* No need .ctrlbit, this is always on
*/
struct clk clk_fout_mpll = {
.name = "fout_mpll",
.id = -1,
};
struct clk clk_fout_mpll_div2 = {
.name = "fout_mpll_div2",
.id = -1,
};
/* EPLL clock output */
struct clk clk_fout_epll = {
.name = "fout_epll",
.id = -1,
.ctrlbit = (1 << 31),
};
/* DPLL clock output */
struct clk clk_fout_dpll = {
.name = "fout_dpll",
.id = -1,
.ctrlbit = (1 << 31),
};
/* VPLL clock output */
struct clk clk_fout_vpll = {
.name = "fout_vpll",
.id = -1,
.ctrlbit = (1 << 31),
};
/* Possible clock sources for APLL Mux */
static struct clk *clk_src_apll_list[] = {
[0] = &clk_fin_apll,
[1] = &clk_fout_apll,
};
struct clksrc_sources clk_src_apll = {
.sources = clk_src_apll_list,
.nr_sources = ARRAY_SIZE(clk_src_apll_list),
};
/* Possible clock sources for BPLL Mux */
static struct clk *clk_src_bpll_list[] = {
[0] = &clk_fin_bpll,
[1] = &clk_fout_bpll,
};
struct clksrc_sources clk_src_bpll = {
.sources = clk_src_bpll_list,
.nr_sources = ARRAY_SIZE(clk_src_bpll_list),
};
static struct clk *clk_src_bpll_fout_list[] = {
[0] = &clk_fout_bpll_div2,
[1] = &clk_fout_bpll,
};
struct clksrc_sources clk_src_bpll_fout = {
.sources = clk_src_bpll_fout_list,
.nr_sources = ARRAY_SIZE(clk_src_bpll_fout_list),
};
/* Possible clock sources for CPLL Mux */
static struct clk *clk_src_cpll_list[] = {
[0] = &clk_fin_cpll,
[1] = &clk_fout_cpll,
};
struct clksrc_sources clk_src_cpll = {
.sources = clk_src_cpll_list,
.nr_sources = ARRAY_SIZE(clk_src_cpll_list),
};
/* Possible clock sources for MPLL Mux */
static struct clk *clk_src_mpll_list[] = {
[0] = &clk_fin_mpll,
[1] = &clk_fout_mpll,
};
struct clksrc_sources clk_src_mpll = {
.sources = clk_src_mpll_list,
.nr_sources = ARRAY_SIZE(clk_src_mpll_list),
};
static struct clk *clk_src_mpll_fout_list[] = {
[0] = &clk_fout_mpll_div2,
[1] = &clk_fout_mpll,
};
struct clksrc_sources clk_src_mpll_fout = {
.sources = clk_src_mpll_fout_list,
.nr_sources = ARRAY_SIZE(clk_src_mpll_fout_list),
};
/* Possible clock sources for EPLL Mux */
static struct clk *clk_src_epll_list[] = {
[0] = &clk_fin_epll,
[1] = &clk_fout_epll,
};
struct clksrc_sources clk_src_epll = {
.sources = clk_src_epll_list,
.nr_sources = ARRAY_SIZE(clk_src_epll_list),
};
/* Possible clock sources for DPLL Mux */
static struct clk *clk_src_dpll_list[] = {
[0] = &clk_fin_dpll,
[1] = &clk_fout_dpll,
};
struct clksrc_sources clk_src_dpll = {
.sources = clk_src_dpll_list,
.nr_sources = ARRAY_SIZE(clk_src_dpll_list),
};
struct clk clk_vpll = {
.name = "vpll",
.id = -1,
};
int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable)
{
unsigned int ctrlbit = clk->ctrlbit;
u32 con;
con = __raw_readl(reg);
con = enable ? (con | ctrlbit) : (con & ~ctrlbit);
__raw_writel(con, reg);
return 0;
}
int s5p_epll_enable(struct clk *clk, int enable)
{
unsigned int ctrlbit = clk->ctrlbit;
unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
if (enable)
__raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
else
__raw_writel(epll_con, S5P_EPLL_CON);
return 0;
}
unsigned long s5p_epll_get_rate(struct clk *clk)
{
return clk->rate;
}
int s5p_spdif_set_rate(struct clk *clk, unsigned long rate)
{
struct clk *pclk;
int ret;
pclk = clk_get_parent(clk);
if (IS_ERR(pclk))
return -EINVAL;
ret = pclk->ops->set_rate(pclk, rate);
clk_put(pclk);
return ret;
}
unsigned long s5p_spdif_get_rate(struct clk *clk)
{
struct clk *pclk;
int rate;
pclk = clk_get_parent(clk);
if (IS_ERR(pclk))
return -EINVAL;
rate = pclk->ops->get_rate(pclk);
clk_put(pclk);
return rate;
}
struct clk_ops s5p_sclk_spdif_ops = {
.set_rate = s5p_spdif_set_rate,
.get_rate = s5p_spdif_get_rate,
};
static struct clk *s5p_clks[] __initdata = {
&clk_ext_xtal_mux,
&clk_48m,
&s5p_clk_27m,
&clk_fout_apll,
&clk_fout_mpll,
&clk_fout_epll,
&clk_fout_dpll,
&clk_fout_vpll,
&clk_vpll,
&clk_xusbxti,
};
void __init s5p_register_clocks(unsigned long xtal_freq)
{
int ret;
clk_ext_xtal_mux.rate = xtal_freq;
ret = s3c24xx_register_clocks(s5p_clks, ARRAY_SIZE(s5p_clks));
if (ret > 0)
printk(KERN_ERR "Failed to register s5p clocks\n");
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2010-2011 Samsung Electronics Co.Ltd
*
* Base S5P MFC resource and device definitions
*
* 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/interrupt.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/memblock.h>
#include <linux/ioport.h>
#include <linux/of_fdt.h>
#include <linux/of.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include <plat/devs.h>
#include <plat/mfc.h>
static struct resource s5p_mfc_resource[] = {
[0] = DEFINE_RES_MEM(S5P_PA_MFC, SZ_64K),
[1] = DEFINE_RES_IRQ(IRQ_MFC),
};
struct platform_device s5p_device_mfc = {
.name = "s5p-mfc",
.id = -1,
.num_resources = ARRAY_SIZE(s5p_mfc_resource),
.resource = s5p_mfc_resource,
};
/*
* MFC hardware has 2 memory interfaces which are modelled as two separate
* platform devices to let dma-mapping distinguish between them.
*
* MFC parent device (s5p_device_mfc) must be registered before memory
* interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
*/
struct platform_device s5p_device_mfc_l = {
.name = "s5p-mfc-l",
.id = -1,
.dev = {
.parent = &s5p_device_mfc.dev,
.dma_mask = &s5p_device_mfc_l.dev.coherent_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
struct platform_device s5p_device_mfc_r = {
.name = "s5p-mfc-r",
.id = -1,
.dev = {
.parent = &s5p_device_mfc.dev,
.dma_mask = &s5p_device_mfc_r.dev.coherent_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
struct s5p_mfc_reserved_mem {
phys_addr_t base;
unsigned long size;
struct device *dev;
};
static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata;
void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
phys_addr_t lbase, unsigned int lsize)
{
int i;
s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev;
s5p_mfc_mem[0].base = rbase;
s5p_mfc_mem[0].size = rsize;
s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev;
s5p_mfc_mem[1].base = lbase;
s5p_mfc_mem[1].size = lsize;
for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
if (memblock_remove(area->base, area->size)) {
printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n",
area->size, (unsigned long) area->base);
area->base = 0;
}
}
}
static int __init s5p_mfc_memory_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
if (!area->base)
continue;
if (dma_declare_coherent_memory(area->dev, area->base,
area->base, area->size,
DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0)
printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n",
area->size, (unsigned long) area->base);
}
return 0;
}
device_initcall(s5p_mfc_memory_init);
#ifdef CONFIG_OF
int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname,
int depth, void *data)
{
__be32 *prop;
unsigned long len;
struct s5p_mfc_dt_meminfo *mfc_mem = data;
if (!data)
return 0;
if (!of_flat_dt_is_compatible(node, mfc_mem->compatible))
return 0;
prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len);
if (!prop || (len != 2 * sizeof(unsigned long)))
return 0;
mfc_mem->loff = be32_to_cpu(prop[0]);
mfc_mem->lsize = be32_to_cpu(prop[1]);
prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len);
if (!prop || (len != 2 * sizeof(unsigned long)))
return 0;
mfc_mem->roff = be32_to_cpu(prop[0]);
mfc_mem->rsize = be32_to_cpu(prop[1]);
return 1;
}
#endif

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2009,2012 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* Base S5P UART resource and device definitions
*
* 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/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
#include <mach/hardware.h>
#include <mach/map.h>
#include <plat/devs.h>
/* Serial port registrations */
static struct resource s5p_uart0_resource[] = {
[0] = DEFINE_RES_MEM(S5P_PA_UART0, S5P_SZ_UART),
[1] = DEFINE_RES_IRQ(IRQ_UART0),
};
static struct resource s5p_uart1_resource[] = {
[0] = DEFINE_RES_MEM(S5P_PA_UART1, S5P_SZ_UART),
[1] = DEFINE_RES_IRQ(IRQ_UART1),
};
static struct resource s5p_uart2_resource[] = {
[0] = DEFINE_RES_MEM(S5P_PA_UART2, S5P_SZ_UART),
[1] = DEFINE_RES_IRQ(IRQ_UART2),
};
static struct resource s5p_uart3_resource[] = {
#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
[0] = DEFINE_RES_MEM(S5P_PA_UART3, S5P_SZ_UART),
[1] = DEFINE_RES_IRQ(IRQ_UART3),
#endif
};
static struct resource s5p_uart4_resource[] = {
#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
[0] = DEFINE_RES_MEM(S5P_PA_UART4, S5P_SZ_UART),
[1] = DEFINE_RES_IRQ(IRQ_UART4),
#endif
};
static struct resource s5p_uart5_resource[] = {
#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
[0] = DEFINE_RES_MEM(S5P_PA_UART5, S5P_SZ_UART),
[1] = DEFINE_RES_IRQ(IRQ_UART5),
#endif
};
struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = {
[0] = {
.resources = s5p_uart0_resource,
.nr_resources = ARRAY_SIZE(s5p_uart0_resource),
},
[1] = {
.resources = s5p_uart1_resource,
.nr_resources = ARRAY_SIZE(s5p_uart1_resource),
},
[2] = {
.resources = s5p_uart2_resource,
.nr_resources = ARRAY_SIZE(s5p_uart2_resource),
},
[3] = {
.resources = s5p_uart3_resource,
.nr_resources = ARRAY_SIZE(s5p_uart3_resource),
},
[4] = {
.resources = s5p_uart4_resource,
.nr_resources = ARRAY_SIZE(s5p_uart4_resource),
},
[5] = {
.resources = s5p_uart5_resource,
.nr_resources = ARRAY_SIZE(s5p_uart5_resource),
},
};

View File

@@ -0,0 +1,217 @@
/*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* S5P - IRQ EINT support
*
* 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/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/irqchip/arm-vic.h>
#include <plat/regs-irqtype.h>
#include <mach/map.h>
#include <plat/cpu.h>
#include <plat/pm.h>
#include <plat/gpio-cfg.h>
#include <mach/regs-gpio.h>
static inline void s5p_irq_eint_mask(struct irq_data *data)
{
u32 mask;
mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
mask |= eint_irq_to_bit(data->irq);
__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
}
static void s5p_irq_eint_unmask(struct irq_data *data)
{
u32 mask;
mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
mask &= ~(eint_irq_to_bit(data->irq));
__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
}
static inline void s5p_irq_eint_ack(struct irq_data *data)
{
__raw_writel(eint_irq_to_bit(data->irq),
S5P_EINT_PEND(EINT_REG_NR(data->irq)));
}
static void s5p_irq_eint_maskack(struct irq_data *data)
{
/* compiler should in-line these */
s5p_irq_eint_mask(data);
s5p_irq_eint_ack(data);
}
static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type)
{
int offs = EINT_OFFSET(data->irq);
int shift;
u32 ctrl, mask;
u32 newvalue = 0;
switch (type) {
case IRQ_TYPE_EDGE_RISING:
newvalue = S5P_IRQ_TYPE_EDGE_RISING;
break;
case IRQ_TYPE_EDGE_FALLING:
newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
break;
case IRQ_TYPE_EDGE_BOTH:
newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
break;
case IRQ_TYPE_LEVEL_LOW:
newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
break;
case IRQ_TYPE_LEVEL_HIGH:
newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
break;
default:
printk(KERN_ERR "No such irq type %d", type);
return -EINVAL;
}
shift = (offs & 0x7) * 4;
mask = 0x7 << shift;
ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
ctrl &= ~mask;
ctrl |= newvalue << shift;
__raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
if ((0 <= offs) && (offs < 8))
s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
else if ((8 <= offs) && (offs < 16))
s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
else if ((16 <= offs) && (offs < 24))
s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
else if ((24 <= offs) && (offs < 32))
s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
else
printk(KERN_ERR "No such irq number %d", offs);
return 0;
}
static struct irq_chip s5p_irq_eint = {
.name = "s5p-eint",
.irq_mask = s5p_irq_eint_mask,
.irq_unmask = s5p_irq_eint_unmask,
.irq_mask_ack = s5p_irq_eint_maskack,
.irq_ack = s5p_irq_eint_ack,
.irq_set_type = s5p_irq_eint_set_type,
#ifdef CONFIG_PM
.irq_set_wake = s3c_irqext_wake,
#endif
};
/* s5p_irq_demux_eint
*
* This function demuxes the IRQ from the group0 external interrupts,
* from EINTs 16 to 31. It is designed to be inlined into the specific
* handler s5p_irq_demux_eintX_Y.
*
* Each EINT pend/mask registers handle eight of them.
*/
static inline void s5p_irq_demux_eint(unsigned int start)
{
u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
unsigned int irq;
status &= ~mask;
status &= 0xff;
while (status) {
irq = fls(status) - 1;
generic_handle_irq(irq + start);
status &= ~(1 << irq);
}
}
static void s5p_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
{
s5p_irq_demux_eint(IRQ_EINT(16));
s5p_irq_demux_eint(IRQ_EINT(24));
}
static inline void s5p_irq_vic_eint_mask(struct irq_data *data)
{
void __iomem *base = irq_data_get_irq_chip_data(data);
s5p_irq_eint_mask(data);
writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE_CLEAR);
}
static void s5p_irq_vic_eint_unmask(struct irq_data *data)
{
void __iomem *base = irq_data_get_irq_chip_data(data);
s5p_irq_eint_unmask(data);
writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE);
}
static inline void s5p_irq_vic_eint_ack(struct irq_data *data)
{
__raw_writel(eint_irq_to_bit(data->irq),
S5P_EINT_PEND(EINT_REG_NR(data->irq)));
}
static void s5p_irq_vic_eint_maskack(struct irq_data *data)
{
s5p_irq_vic_eint_mask(data);
s5p_irq_vic_eint_ack(data);
}
static struct irq_chip s5p_irq_vic_eint = {
.name = "s5p_vic_eint",
.irq_mask = s5p_irq_vic_eint_mask,
.irq_unmask = s5p_irq_vic_eint_unmask,
.irq_mask_ack = s5p_irq_vic_eint_maskack,
.irq_ack = s5p_irq_vic_eint_ack,
.irq_set_type = s5p_irq_eint_set_type,
#ifdef CONFIG_PM
.irq_set_wake = s3c_irqext_wake,
#endif
};
static int __init s5p_init_irq_eint(void)
{
int irq;
for (irq = IRQ_EINT(0); irq <= IRQ_EINT(15); irq++)
irq_set_chip(irq, &s5p_irq_vic_eint);
for (irq = IRQ_EINT(16); irq <= IRQ_EINT(31); irq++) {
irq_set_chip_and_handler(irq, &s5p_irq_eint, handle_level_irq);
set_irq_flags(irq, IRQF_VALID);
}
irq_set_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31);
return 0;
}
arch_initcall(s5p_init_irq_eint);

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* Author: Kyungmin Park <kyungmin.park@samsung.com>
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
* Author: Marek Szyprowski <m.szyprowski@samsung.com>
*
* 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.
*
*/
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <mach/map.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
#define GPIO_BASE(chip) ((void __iomem *)((unsigned long)((chip)->base) & 0xFFFFF000u))
#define CON_OFFSET 0x700
#define MASK_OFFSET 0x900
#define PEND_OFFSET 0xA00
#define REG_OFFSET(x) ((x) << 2)
struct s5p_gpioint_bank {
struct list_head list;
int start;
int nr_groups;
int irq;
struct samsung_gpio_chip **chips;
void (*handler)(unsigned int, struct irq_desc *);
};
static LIST_HEAD(banks);
static int s5p_gpioint_set_type(struct irq_data *d, unsigned int type)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = gc->chip_types;
unsigned int shift = (d->irq - gc->irq_base) << 2;
switch (type) {
case IRQ_TYPE_EDGE_RISING:
type = S5P_IRQ_TYPE_EDGE_RISING;
break;
case IRQ_TYPE_EDGE_FALLING:
type = S5P_IRQ_TYPE_EDGE_FALLING;
break;
case IRQ_TYPE_EDGE_BOTH:
type = S5P_IRQ_TYPE_EDGE_BOTH;
break;
case IRQ_TYPE_LEVEL_HIGH:
type = S5P_IRQ_TYPE_LEVEL_HIGH;
break;
case IRQ_TYPE_LEVEL_LOW:
type = S5P_IRQ_TYPE_LEVEL_LOW;
break;
case IRQ_TYPE_NONE:
default:
printk(KERN_WARNING "No irq type\n");
return -EINVAL;
}
gc->type_cache &= ~(0x7 << shift);
gc->type_cache |= type << shift;
writel(gc->type_cache, gc->reg_base + ct->regs.type);
return 0;
}
static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
{
struct s5p_gpioint_bank *bank = irq_get_handler_data(irq);
int group, pend_offset, mask_offset;
unsigned int pend, mask;
struct irq_chip *chip = irq_get_chip(irq);
chained_irq_enter(chip, desc);
for (group = 0; group < bank->nr_groups; group++) {
struct samsung_gpio_chip *chip = bank->chips[group];
if (!chip)
continue;
pend_offset = REG_OFFSET(group);
pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
if (!pend)
continue;
mask_offset = REG_OFFSET(group);
mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
pend &= ~mask;
while (pend) {
int offset = fls(pend) - 1;
int real_irq = chip->irq_base + offset;
generic_handle_irq(real_irq);
pend &= ~BIT(offset);
}
}
chained_irq_exit(chip, desc);
}
static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip)
{
static int used_gpioint_groups = 0;
int group = chip->group;
struct s5p_gpioint_bank *b, *bank = NULL;
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT)
return -ENOMEM;
list_for_each_entry(b, &banks, list) {
if (group >= b->start && group < b->start + b->nr_groups) {
bank = b;
break;
}
}
if (!bank)
return -EINVAL;
if (!bank->handler) {
bank->chips = kzalloc(sizeof(struct samsung_gpio_chip *) *
bank->nr_groups, GFP_KERNEL);
if (!bank->chips)
return -ENOMEM;
irq_set_chained_handler(bank->irq, s5p_gpioint_handler);
irq_set_handler_data(bank->irq, bank);
bank->handler = s5p_gpioint_handler;
printk(KERN_INFO "Registered chained gpio int handler for interrupt %d.\n",
bank->irq);
}
/*
* chained GPIO irq has been successfully registered, allocate new gpio
* int group and assign irq nubmers
*/
chip->irq_base = S5P_GPIOINT_BASE +
used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE;
used_gpioint_groups++;
bank->chips[group - bank->start] = chip;
gc = irq_alloc_generic_chip("s5p_gpioint", 1, chip->irq_base,
GPIO_BASE(chip),
handle_level_irq);
if (!gc)
return -ENOMEM;
ct = gc->chip_types;
ct->chip.irq_ack = irq_gc_ack_set_bit;
ct->chip.irq_mask = irq_gc_mask_set_bit;
ct->chip.irq_unmask = irq_gc_mask_clr_bit;
ct->chip.irq_set_type = s5p_gpioint_set_type,
ct->regs.ack = PEND_OFFSET + REG_OFFSET(group - bank->start);
ct->regs.mask = MASK_OFFSET + REG_OFFSET(group - bank->start);
ct->regs.type = CON_OFFSET + REG_OFFSET(group - bank->start);
irq_setup_generic_chip(gc, IRQ_MSK(chip->chip.ngpio),
IRQ_GC_INIT_MASK_CACHE,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
return 0;
}
int __init s5p_register_gpio_interrupt(int pin)
{
struct samsung_gpio_chip *my_chip = samsung_gpiolib_getchip(pin);
int offset, group;
int ret;
if (!my_chip)
return -EINVAL;
offset = pin - my_chip->chip.base;
group = my_chip->group;
/* check if the group has been already registered */
if (my_chip->irq_base)
goto success;
/* register gpio group */
ret = s5p_gpioint_add(my_chip);
if (ret == 0) {
my_chip->chip.to_irq = samsung_gpiolib_to_irq;
printk(KERN_INFO "Registered interrupt support for gpio group %d.\n",
group);
goto success;
}
return ret;
success:
my_chip->bitmap_gpio_int |= BIT(offset);
return my_chip->irq_base + offset;
}
int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups)
{
struct s5p_gpioint_bank *bank;
bank = kzalloc(sizeof(*bank), GFP_KERNEL);
if (!bank)
return -ENOMEM;
bank->start = start;
bank->nr_groups = nr_groups;
bank->irq = chain_irq;
list_add_tail(&bank->list, &banks);
return 0;
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Based on arch/arm/plat-s3c24xx/irq-pm.c,
* Copyright (c) 2003,2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* 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/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <plat/cpu.h>
#include <plat/irqs.h>
#include <plat/pm.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/regs-irq.h>
/* state for IRQs over sleep */
/* default is to allow for EINT0..EINT31, and IRQ_RTC_TIC, IRQ_RTC_ALARM,
* as wakeup sources
*
* set bit to 1 in allow bitfield to enable the wakeup settings on it
*/
unsigned long s3c_irqwake_intallow = 0x00000006L;
unsigned long s3c_irqwake_eintallow = 0xffffffffL;
int s3c_irq_wake(struct irq_data *data, unsigned int state)
{
unsigned long irqbit;
unsigned int irq_rtc_tic, irq_rtc_alarm;
#ifdef CONFIG_ARCH_EXYNOS
if (soc_is_exynos5250()) {
irq_rtc_tic = EXYNOS5_IRQ_RTC_TIC;
irq_rtc_alarm = EXYNOS5_IRQ_RTC_ALARM;
} else {
irq_rtc_tic = EXYNOS4_IRQ_RTC_TIC;
irq_rtc_alarm = EXYNOS4_IRQ_RTC_ALARM;
}
#else
irq_rtc_tic = IRQ_RTC_TIC;
irq_rtc_alarm = IRQ_RTC_ALARM;
#endif
if (data->irq == irq_rtc_tic || data->irq == irq_rtc_alarm) {
irqbit = 1 << (data->irq + 1 - irq_rtc_alarm);
if (!state)
s3c_irqwake_intmask |= irqbit;
else
s3c_irqwake_intmask &= ~irqbit;
} else {
return -ENOENT;
}
return 0;
}
static struct sleep_save eint_save[] = {
SAVE_ITEM(S5P_EINT_CON(0)),
SAVE_ITEM(S5P_EINT_CON(1)),
SAVE_ITEM(S5P_EINT_CON(2)),
SAVE_ITEM(S5P_EINT_CON(3)),
SAVE_ITEM(S5P_EINT_FLTCON(0)),
SAVE_ITEM(S5P_EINT_FLTCON(1)),
SAVE_ITEM(S5P_EINT_FLTCON(2)),
SAVE_ITEM(S5P_EINT_FLTCON(3)),
SAVE_ITEM(S5P_EINT_FLTCON(4)),
SAVE_ITEM(S5P_EINT_FLTCON(5)),
SAVE_ITEM(S5P_EINT_FLTCON(6)),
SAVE_ITEM(S5P_EINT_FLTCON(7)),
SAVE_ITEM(S5P_EINT_MASK(0)),
SAVE_ITEM(S5P_EINT_MASK(1)),
SAVE_ITEM(S5P_EINT_MASK(2)),
SAVE_ITEM(S5P_EINT_MASK(3)),
};
int s3c24xx_irq_suspend(void)
{
s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save));
return 0;
}
void s3c24xx_irq_resume(void)
{
s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save));
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2009 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S5P - Interrupt handling
*
* 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/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/irqchip/arm-vic.h>
#include <mach/irqs.h>
#include <mach/map.h>
#include <plat/regs-timer.h>
#include <plat/cpu.h>
#include <plat/irq-vic-timer.h>
void __init s5p_init_irq(u32 *vic, u32 num_vic)
{
#ifdef CONFIG_ARM_VIC
int irq;
/* initialize the VICs */
for (irq = 0; irq < num_vic; irq++)
vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
#endif
s3c_init_vic_timer_irq(5, IRQ_TIMER0);
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* S5P Power Manager (Suspend-To-RAM) support
*
* Based on arch/arm/plat-s3c24xx/pm.c
* Copyright (c) 2004,2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* 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/suspend.h>
#include <plat/pm.h>
#define PFX "s5p pm: "
/* s3c_pm_configure_extint
*
* configure all external interrupt pins
*/
void s3c_pm_configure_extint(void)
{
/* nothing here yet */
}
void s3c_pm_restore_core(void)
{
/* nothing here yet */
}
void s3c_pm_save_core(void)
{
/* nothing here yet */
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Common S5P Sleep Code
* Based on S3C64XX sleep code by:
* Ben Dooks, (c) 2008 Simtec Electronics
*
* 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
*/
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/hardware/cache-l2x0.h>
#define CPU_MASK 0xff0ffff0
#define CPU_CORTEX_A9 0x410fc090
/*
* The following code is located into the .data section. This is to
* allow l2x0_regs_phys to be accessed with a relative load while we
* can't rely on any MMU translation. We could have put l2x0_regs_phys
* in the .text section as well, but some setups might insist on it to
* be truly read-only. (Reference from: arch/arm/kernel/sleep.S)
*/
.data
.align
/*
* sleep magic, to allow the bootloader to check for an valid
* image to resume to. Must be the first word before the
* s3c_cpu_resume entry.
*/
.word 0x2bedf00d
/*
* s3c_cpu_resume
*
* resume code entry for bootloader to call
*/
ENTRY(s3c_cpu_resume)
#ifdef CONFIG_CACHE_L2X0
mrc p15, 0, r0, c0, c0, 0
ldr r1, =CPU_MASK
and r0, r0, r1
ldr r1, =CPU_CORTEX_A9
cmp r0, r1
bne resume_l2on
adr r0, l2x0_regs_phys
ldr r0, [r0]
ldr r1, [r0, #L2X0_R_PHY_BASE]
ldr r2, [r1, #L2X0_CTRL]
tst r2, #0x1
bne resume_l2on
ldr r2, [r0, #L2X0_R_AUX_CTRL]
str r2, [r1, #L2X0_AUX_CTRL]
ldr r2, [r0, #L2X0_R_TAG_LATENCY]
str r2, [r1, #L2X0_TAG_LATENCY_CTRL]
ldr r2, [r0, #L2X0_R_DATA_LATENCY]
str r2, [r1, #L2X0_DATA_LATENCY_CTRL]
ldr r2, [r0, #L2X0_R_PREFETCH_CTRL]
str r2, [r1, #L2X0_PREFETCH_CTRL]
ldr r2, [r0, #L2X0_R_PWR_CTRL]
str r2, [r1, #L2X0_POWER_CTRL]
mov r2, #1
str r2, [r1, #L2X0_CTRL]
resume_l2on:
#endif
b cpu_resume
ENDPROC(s3c_cpu_resume)
#ifdef CONFIG_CACHE_L2X0
.globl l2x0_regs_phys
l2x0_regs_phys:
.long 0
#endif

View File

@@ -0,0 +1,394 @@
/*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* samsung - Common hr-timer support (s3c and s5p)
*
* 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/interrupt.h>
#include <linux/irq.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/platform_device.h>
#include <asm/smp_twd.h>
#include <asm/mach/time.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/sched_clock.h>
#include <mach/map.h>
#include <plat/devs.h>
#include <plat/regs-timer.h>
#include <plat/samsung-time.h>
static struct clk *tin_event;
static struct clk *tin_source;
static struct clk *tdiv_event;
static struct clk *tdiv_source;
static struct clk *timerclk;
static struct samsung_timer_source timer_source;
static unsigned long clock_count_per_tick;
static void samsung_timer_resume(void);
static void samsung_time_stop(enum samsung_timer_mode mode)
{
unsigned long tcon;
tcon = __raw_readl(S3C2410_TCON);
switch (mode) {
case SAMSUNG_PWM0:
tcon &= ~S3C2410_TCON_T0START;
break;
case SAMSUNG_PWM1:
tcon &= ~S3C2410_TCON_T1START;
break;
case SAMSUNG_PWM2:
tcon &= ~S3C2410_TCON_T2START;
break;
case SAMSUNG_PWM3:
tcon &= ~S3C2410_TCON_T3START;
break;
case SAMSUNG_PWM4:
tcon &= ~S3C2410_TCON_T4START;
break;
default:
printk(KERN_ERR "Invalid Timer %d\n", mode);
break;
}
__raw_writel(tcon, S3C2410_TCON);
}
static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
{
unsigned long tcon;
tcon = __raw_readl(S3C2410_TCON);
tcnt--;
switch (mode) {
case SAMSUNG_PWM0:
tcon &= ~(0x0f << 0);
tcon |= S3C2410_TCON_T0MANUALUPD;
break;
case SAMSUNG_PWM1:
tcon &= ~(0x0f << 8);
tcon |= S3C2410_TCON_T1MANUALUPD;
break;
case SAMSUNG_PWM2:
tcon &= ~(0x0f << 12);
tcon |= S3C2410_TCON_T2MANUALUPD;
break;
case SAMSUNG_PWM3:
tcon &= ~(0x0f << 16);
tcon |= S3C2410_TCON_T3MANUALUPD;
break;
case SAMSUNG_PWM4:
tcon &= ~(0x07 << 20);
tcon |= S3C2410_TCON_T4MANUALUPD;
break;
default:
printk(KERN_ERR "Invalid Timer %d\n", mode);
break;
}
__raw_writel(tcnt, S3C2410_TCNTB(mode));
__raw_writel(tcnt, S3C2410_TCMPB(mode));
__raw_writel(tcon, S3C2410_TCON);
}
static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
{
unsigned long tcon;
tcon = __raw_readl(S3C2410_TCON);
switch (mode) {
case SAMSUNG_PWM0:
tcon |= S3C2410_TCON_T0START;
tcon &= ~S3C2410_TCON_T0MANUALUPD;
if (periodic)
tcon |= S3C2410_TCON_T0RELOAD;
else
tcon &= ~S3C2410_TCON_T0RELOAD;
break;
case SAMSUNG_PWM1:
tcon |= S3C2410_TCON_T1START;
tcon &= ~S3C2410_TCON_T1MANUALUPD;
if (periodic)
tcon |= S3C2410_TCON_T1RELOAD;
else
tcon &= ~S3C2410_TCON_T1RELOAD;
break;
case SAMSUNG_PWM2:
tcon |= S3C2410_TCON_T2START;
tcon &= ~S3C2410_TCON_T2MANUALUPD;
if (periodic)
tcon |= S3C2410_TCON_T2RELOAD;
else
tcon &= ~S3C2410_TCON_T2RELOAD;
break;
case SAMSUNG_PWM3:
tcon |= S3C2410_TCON_T3START;
tcon &= ~S3C2410_TCON_T3MANUALUPD;
if (periodic)
tcon |= S3C2410_TCON_T3RELOAD;
else
tcon &= ~S3C2410_TCON_T3RELOAD;
break;
case SAMSUNG_PWM4:
tcon |= S3C2410_TCON_T4START;
tcon &= ~S3C2410_TCON_T4MANUALUPD;
if (periodic)
tcon |= S3C2410_TCON_T4RELOAD;
else
tcon &= ~S3C2410_TCON_T4RELOAD;
break;
default:
printk(KERN_ERR "Invalid Timer %d\n", mode);
break;
}
__raw_writel(tcon, S3C2410_TCON);
}
static int samsung_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
samsung_time_setup(timer_source.event_id, cycles);
samsung_time_start(timer_source.event_id, NON_PERIODIC);
return 0;
}
static void samsung_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
samsung_time_stop(timer_source.event_id);
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
samsung_time_setup(timer_source.event_id, clock_count_per_tick);
samsung_time_start(timer_source.event_id, PERIODIC);
break;
case CLOCK_EVT_MODE_ONESHOT:
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
break;
case CLOCK_EVT_MODE_RESUME:
samsung_timer_resume();
break;
}
}
static void samsung_timer_resume(void)
{
/* event timer restart */
samsung_time_setup(timer_source.event_id, clock_count_per_tick);
samsung_time_start(timer_source.event_id, PERIODIC);
/* source timer restart */
samsung_time_setup(timer_source.source_id, TCNT_MAX);
samsung_time_start(timer_source.source_id, PERIODIC);
}
void __init samsung_set_timer_source(enum samsung_timer_mode event,
enum samsung_timer_mode source)
{
s3c_device_timer[event].dev.bus = &platform_bus_type;
s3c_device_timer[source].dev.bus = &platform_bus_type;
timer_source.event_id = event;
timer_source.source_id = source;
}
static struct clock_event_device time_event_device = {
.name = "samsung_event_timer",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.rating = 200,
.set_next_event = samsung_set_next_event,
.set_mode = samsung_set_mode,
};
static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;
evt->event_handler(evt);
return IRQ_HANDLED;
}
static struct irqaction samsung_clock_event_irq = {
.name = "samsung_time_irq",
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
.handler = samsung_clock_event_isr,
.dev_id = &time_event_device,
};
static void __init samsung_clockevent_init(void)
{
unsigned long pclk;
unsigned long clock_rate;
unsigned int irq_number;
struct clk *tscaler;
pclk = clk_get_rate(timerclk);
tscaler = clk_get_parent(tdiv_event);
clk_set_rate(tscaler, pclk / TSCALER_DIV);
clk_set_rate(tdiv_event, pclk / TDIV);
clk_set_parent(tin_event, tdiv_event);
clock_rate = clk_get_rate(tin_event);
clock_count_per_tick = clock_rate / HZ;
time_event_device.cpumask = cpumask_of(0);
clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
irq_number = timer_source.event_id + IRQ_TIMER0;
setup_irq(irq_number, &samsung_clock_event_irq);
}
static void __iomem *samsung_timer_reg(void)
{
unsigned long offset = 0;
switch (timer_source.source_id) {
case SAMSUNG_PWM0:
case SAMSUNG_PWM1:
case SAMSUNG_PWM2:
case SAMSUNG_PWM3:
offset = (timer_source.source_id * 0x0c) + 0x14;
break;
case SAMSUNG_PWM4:
offset = 0x40;
break;
default:
printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
return NULL;
}
return S3C_TIMERREG(offset);
}
/*
* Override the global weak sched_clock symbol with this
* local implementation which uses the clocksource to get some
* better resolution when scheduling the kernel. We accept that
* this wraps around for now, since it is just a relative time
* stamp. (Inspired by U300 implementation.)
*/
static u32 notrace samsung_read_sched_clock(void)
{
void __iomem *reg = samsung_timer_reg();
if (!reg)
return 0;
return ~__raw_readl(reg);
}
static void __init samsung_clocksource_init(void)
{
unsigned long pclk;
unsigned long clock_rate;
pclk = clk_get_rate(timerclk);
clk_set_rate(tdiv_source, pclk / TDIV);
clk_set_parent(tin_source, tdiv_source);
clock_rate = clk_get_rate(tin_source);
samsung_time_setup(timer_source.source_id, TCNT_MAX);
samsung_time_start(timer_source.source_id, PERIODIC);
setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
if (clocksource_mmio_init(samsung_timer_reg(), "samsung_clocksource_timer",
clock_rate, 250, TSIZE, clocksource_mmio_readl_down))
panic("samsung_clocksource_timer: can't register clocksource\n");
}
static void __init samsung_timer_resources(void)
{
unsigned long event_id = timer_source.event_id;
unsigned long source_id = timer_source.source_id;
char devname[15];
timerclk = clk_get(NULL, "timers");
if (IS_ERR(timerclk))
panic("failed to get timers clock for timer");
clk_enable(timerclk);
sprintf(devname, "s3c24xx-pwm.%lu", event_id);
s3c_device_timer[event_id].id = event_id;
s3c_device_timer[event_id].dev.init_name = devname;
tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin");
if (IS_ERR(tin_event))
panic("failed to get pwm-tin clock for event timer");
tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv");
if (IS_ERR(tdiv_event))
panic("failed to get pwm-tdiv clock for event timer");
clk_enable(tin_event);
sprintf(devname, "s3c24xx-pwm.%lu", source_id);
s3c_device_timer[source_id].id = source_id;
s3c_device_timer[source_id].dev.init_name = devname;
tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin");
if (IS_ERR(tin_source))
panic("failed to get pwm-tin clock for source timer");
tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv");
if (IS_ERR(tdiv_source))
panic("failed to get pwm-tdiv clock for source timer");
clk_enable(tin_source);
}
void __init samsung_timer_init(void)
{
samsung_timer_resources();
samsung_clockevent_init();
samsung_clocksource_init();
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
*
* Helper functions for S3C24XX/S3C64XX SoC series CAMIF driver
*
* 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/gpio.h>
#include <plat/gpio-cfg.h>
/* Number of camera port pins, without FIELD */
#define S3C_CAMIF_NUM_GPIOS 13
/* Default camera port configuration helpers. */
static void camif_get_gpios(int *gpio_start, int *gpio_reset)
{
#ifdef CONFIG_ARCH_S3C24XX
*gpio_start = S3C2410_GPJ(0);
*gpio_reset = S3C2410_GPJ(12);
#else
/* s3c64xx */
*gpio_start = S3C64XX_GPF(0);
*gpio_reset = S3C64XX_GPF(3);
#endif
}
int s3c_camif_gpio_get(void)
{
int gpio_start, gpio_reset;
int ret, i;
camif_get_gpios(&gpio_start, &gpio_reset);
for (i = 0; i < S3C_CAMIF_NUM_GPIOS; i++) {
int gpio = gpio_start + i;
if (gpio == gpio_reset)
continue;
ret = gpio_request(gpio, "camif");
if (!ret)
ret = s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
if (ret) {
pr_err("failed to configure GPIO %d\n", gpio);
for (--i; i >= 0; i--)
gpio_free(gpio--);
return ret;
}
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
return 0;
}
void s3c_camif_gpio_put(void)
{
int i, gpio_start, gpio_reset;
camif_get_gpios(&gpio_start, &gpio_reset);
for (i = 0; i < S3C_CAMIF_NUM_GPIOS; i++) {
int gpio = gpio_start + i;
if (gpio != gpio_reset)
gpio_free(gpio);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
*
* S5P - Helper functions for MIPI-CSIS and MIPI-DSIM D-PHY control
*
* 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/export.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <mach/regs-clock.h>
static int __s5p_mipi_phy_control(int id, bool on, u32 reset)
{
static DEFINE_SPINLOCK(lock);
void __iomem *addr;
unsigned long flags;
u32 cfg;
id = max(0, id);
if (id > 1)
return -EINVAL;
addr = S5P_MIPI_DPHY_CONTROL(id);
spin_lock_irqsave(&lock, flags);
cfg = __raw_readl(addr);
cfg = on ? (cfg | reset) : (cfg & ~reset);
__raw_writel(cfg, addr);
if (on) {
cfg |= S5P_MIPI_DPHY_ENABLE;
} else if (!(cfg & (S5P_MIPI_DPHY_SRESETN |
S5P_MIPI_DPHY_MRESETN) & ~reset)) {
cfg &= ~S5P_MIPI_DPHY_ENABLE;
}
__raw_writel(cfg, addr);
spin_unlock_irqrestore(&lock, flags);
return 0;
}
int s5p_csis_phy_enable(int id, bool on)
{
return __s5p_mipi_phy_control(id, on, S5P_MIPI_DPHY_SRESETN);
}
EXPORT_SYMBOL(s5p_csis_phy_enable);
int s5p_dsim_phy_enable(struct platform_device *pdev, bool on)
{
return __s5p_mipi_phy_control(pdev->id, on, S5P_MIPI_DPHY_MRESETN);
}
EXPORT_SYMBOL(s5p_dsim_phy_enable);

View File

@@ -0,0 +1,47 @@
/* arch/arm/plat-samsung/wakeup-mask.c
*
* Copyright 2010 Ben Dooks <ben-linux@fluff.org>
*
* Support for wakeup mask interrupts on newer SoCs
*
* 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/spinlock.h>
#include <linux/device.h>
#include <linux/types.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <plat/wakeup-mask.h>
#include <plat/pm.h>
void samsung_sync_wakemask(void __iomem *reg,
struct samsung_wakeup_mask *mask, int nr_mask)
{
struct irq_data *data;
u32 val;
val = __raw_readl(reg);
for (; nr_mask > 0; nr_mask--, mask++) {
if (mask->irq == NO_WAKEUP_IRQ) {
val |= mask->bit;
continue;
}
data = irq_get_irq_data(mask->irq);
/* bit of a liberty to read this directly from irq_data. */
if (irqd_is_wakeup_set(data))
val &= ~mask->bit;
else
val |= mask->bit;
}
printk(KERN_INFO "wakemask %08x => %08x\n", __raw_readl(reg), val);
__raw_writel(val, reg);
}