提交 349e1fba 编写于 作者: L Linus Torvalds

Merge branch 'for-linus/samsung4' of git://git.fluff.org/bjdooks/linux

* 'for-linus/samsung4' of git://git.fluff.org/bjdooks/linux: (98 commits)
  Input: s3c24xx_ts - depend on SAMSUNG_DEV_TS and update menu entry
  Input: s3c24xx_ts - Add FEAT for Samsung touchscreen support
  Input: s3c24xx_ts - Implement generic GPIO configuration callback
  ARM: SAMSUNG: Move s3c64xx dev-ts.c to plat-samsung and rename configuration
  ARM: SAMSUNG: Implements cfg_gpio function for Samsung touchscreen
  ARM: S3C64XX: Add touchscreen platform device definition
  ARM: SAMSUNG: Move mach/ts.h to plat/ts.h
  ARM: S5PC100: Move i2c helpers from plat-s5pc1xx to mach-s5pc100
  ARM: S5PC100: Move frame buffer helpers from plat-s5pc1xx to mach-s5pc100
  ARM: S5PC100: gpio.h cleanup
  ARM: S5PC100: Move gpio support from plat-s5pc1xx to mach-s5pc100
  ARM: S5PC100: Use common functions for gpiolib implementation
  drivers: serial: S5PC100 serial driver cleanup
  ARM: S5PC100: Pre-requisite clock patch for plat-s5pc1xx to plat-s5p move
  ARM: SAMSUNG: Copy common I2C0 device helpers to machine directories
  ARM: SAMSUNG: move driver strength gpio configuration helper to common dir
  ARM: S5PV210: Add GPIOlib support
  ARM: SAMSUNGy: fix broken timer irq base
  ARM: SMDK6440: Add audio devices on board
  ARM: S5P6440: Add audio platform devices
  ...
......@@ -110,6 +110,8 @@ CHECKFLAGS += -D__arm__
head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
textofs-y := 0x00008000
textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
# We don't want the htc bootloader to corrupt kernel during resume
textofs-$(CONFIG_PM_H1940) := 0x00108000
# SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
ifeq ($(CONFIG_ARCH_SA1100),y)
textofs-$(CONFIG_SA1111) := 0x00208000
......
......@@ -77,6 +77,7 @@ config ARCH_H1940
select PM_H1940 if PM
select S3C_DEV_USB_HOST
select S3C_DEV_NAND
select S3C2410_SETUP_TS
help
Say Y here if you are using the HP IPAQ H1940
......@@ -96,12 +97,19 @@ config PM_H1940
config MACH_N30
bool "Acer N30 family"
select CPU_S3C2410
select MACH_N35
select S3C_DEV_USB_HOST
select S3C_DEV_NAND
help
Say Y here if you want suppt for the Acer N30, Acer N35,
Navman PiN570, Yakumo AlphaX or Airis NC05 PDAs.
config MACH_N35
bool
help
Internal node in order to enable support for Acer N35 if Acer N30 is
selected.
config ARCH_BAST
bool "Simtec Electronics BAST (EB2410ITX)"
select CPU_S3C2410
......@@ -111,6 +119,7 @@ config ARCH_BAST
select MACH_BAST_IDE
select S3C24XX_DCLK
select ISA
select S3C_DEV_HWMON
select S3C_DEV_USB_HOST
select S3C_DEV_NAND
help
......
zreladdr-y := 0x30008000
params_phys-y := 0x30000100
ifeq ($(CONFIG_PM_H1940),y)
zreladdr-y := 0x30108000
params_phys-y := 0x30100100
else
zreladdr-y := 0x30008000
params_phys-y := 0x30000100
endif
......@@ -16,15 +16,28 @@
#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
#define S3C2410_GPIO_BANKA (32*0)
#define S3C2410_GPIO_BANKB (32*1)
#define S3C2410_GPIO_BANKC (32*2)
#define S3C2410_GPIO_BANKD (32*3)
#define S3C2410_GPIO_BANKE (32*4)
#define S3C2410_GPIO_BANKF (32*5)
#define S3C2410_GPIO_BANKG (32*6)
#define S3C2410_GPIO_BANKH (32*7)
/* GPIO sizes for various SoCs:
*
* 2442
* 2410 2412 2440 2443 2416
* ---- ---- ---- ---- ----
* A 23 22 25 16 25
* B 11 11 11 11 9
* C 16 15 16 16 16
* D 16 16 16 16 16
* E 16 16 16 16 16
* F 8 8 8 8 8
* G 16 16 16 16 8
* H 11 11 9 15 15
* J -- -- 13 16 --
* K -- -- -- -- 16
* L -- -- -- 15 7
* M -- -- -- 2 2
*/
/* GPIO bank sizes */
#define S3C2410_GPIO_A_NR (32)
#define S3C2410_GPIO_B_NR (32)
......
......@@ -23,11 +23,11 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
{
struct s3c_gpio_chip *chip;
if (pin > S3C2410_GPG(10))
if (pin > S3C_GPIO_END)
return NULL;
chip = &s3c24xx_gpios[pin/32];
return (S3C2410_GPIO_OFFSET(pin) < chip->chip.ngpio) ? chip : NULL;
return ((pin - chip->chip.base) < chip->chip.ngpio) ? chip : NULL;
}
#endif /* __ASM_ARCH_GPIO_CORE_H */
......@@ -20,10 +20,18 @@
* devices that need GPIO.
*/
#ifdef CONFIG_CPU_S3C244X
#define ARCH_NR_GPIOS (32 * 9 + CONFIG_S3C24XX_GPIO_EXTRA)
#else
#define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA)
#endif
#include <asm-generic/gpio.h>
#include <mach/gpio-nrs.h>
#include <mach/gpio-fns.h>
#ifdef CONFIG_CPU_S3C24XX
#define S3C_GPIO_END (S3C2410_GPIO_BANKJ + 32)
#else
#define S3C_GPIO_END (S3C2410_GPIO_BANKH + 32)
#endif
......@@ -187,6 +187,9 @@
#define IRQ_S3CUART_TX3 IRQ_S3C2443_TX3
#define IRQ_S3CUART_ERR3 IRQ_S3C2443_ERR3
#define IRQ_LCD_VSYNC IRQ_S3C2443_LCD3
#define IRQ_LCD_SYSTEM IRQ_S3C2443_LCD2
#ifdef CONFIG_CPU_S3C2440
#define IRQ_S3C244x_AC97 IRQ_S3C2440_AC97
#else
......
......@@ -67,6 +67,8 @@
#define S3C2443_PA_HSMMC (0x4A800000)
#define S3C2416_PA_HSMMC0 (0x4AC00000)
#define S3C2443_PA_FB (0x4C800000)
/* S3C2412 memory and IO controls */
#define S3C2412_PA_SSMC (0x4F000000)
#define S3C2412_VA_SSMC S3C_ADDR_CPU(0x00000000)
......@@ -106,6 +108,7 @@
#define S3C24XX_PA_SDI S3C2410_PA_SDI
#define S3C24XX_PA_NAND S3C2410_PA_NAND
#define S3C_PA_FB S3C2443_PA_FB
#define S3C_PA_IIC S3C2410_PA_IIC
#define S3C_PA_UART S3C24XX_PA_UART
#define S3C_PA_USBHOST S3C2410_PA_USBHOST
......
......@@ -17,29 +17,11 @@
#include <mach/gpio-nrs.h>
#ifdef CONFIG_CPU_S3C2400
#define S3C24XX_GPIO_BASE(x) S3C2400_GPIO_BASE(x)
#define S3C24XX_MISCCR S3C2400_MISCCR
#define S3C24XX_MISCCR S3C2400_MISCCR
#else
#define S3C24XX_GPIO_BASE(x) S3C2410_GPIO_BASE(x)
#define S3C24XX_MISCCR S3C24XX_GPIOREG2(0x80)
#define S3C24XX_MISCCR S3C24XX_GPIOREG2(0x80)
#endif /* CONFIG_CPU_S3C2400 */
/* S3C2400 doesn't have a 1:1 mapping to S3C2410 gpio base pins */
#define S3C2400_BANKNUM(pin) (((pin) & ~31) / 32)
#define S3C2400_BASEA2B(pin) ((((pin) & ~31) >> 2))
#define S3C2400_BASEC2H(pin) ((S3C2400_BANKNUM(pin) * 10) + \
(2 * (S3C2400_BANKNUM(pin)-2)))
#define S3C2400_GPIO_BASE(pin) (pin < S3C2410_GPIO_BANKC ? \
S3C2400_BASEA2B(pin)+S3C24XX_VA_GPIO : \
S3C2400_BASEC2H(pin)+S3C24XX_VA_GPIO)
#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
/* general configuration options */
#define S3C2410_GPIO_LEAVE (0xFFFFFFFF)
......
......@@ -83,8 +83,7 @@
#define S3C2443_HCLKCON_DMA4 (1<<4)
#define S3C2443_HCLKCON_DMA5 (1<<5)
#define S3C2443_HCLKCON_CAMIF (1<<8)
#define S3C2443_HCLKCON_DISP (1<<9)
#define S3C2443_HCLKCON_LCDC (1<<10)
#define S3C2443_HCLKCON_LCDC (1<<9)
#define S3C2443_HCLKCON_USBH (1<<11)
#define S3C2443_HCLKCON_USBD (1<<12)
#define S3C2443_HCLKCON_HSMMC (1<<16)
......
......@@ -633,7 +633,7 @@ static void __init bast_map_io(void)
s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks));
s3c_device_hwmon.dev.platform_data = &bast_hwmon_info;
s3c_hwmon_set_platdata(&bast_hwmon_info);
s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
s3c24xx_init_clocks(0);
......
......@@ -46,7 +46,6 @@
#include <mach/h1940.h>
#include <mach/h1940-latch.h>
#include <mach/fb.h>
#include <mach/ts.h>
#include <plat/udc.h>
#include <plat/iic.h>
......@@ -57,6 +56,7 @@
#include <plat/pll.h>
#include <plat/pm.h>
#include <plat/mci.h>
#include <plat/ts.h>
static struct map_desc h1940_iodesc[] __initdata = {
[0] = {
......@@ -146,6 +146,7 @@ static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
.delay = 10000,
.presc = 49,
.oversampling_shift = 2,
.cfg_gpio = s3c24xx_ts_cfg_gpio,
};
/**
......@@ -163,8 +164,8 @@ static struct s3c2410fb_display h1940_lcd __initdata = {
.xres = 240,
.yres = 320,
.bpp = 16,
.left_margin = 20,
.right_margin = 8,
.left_margin = 8,
.right_margin = 20,
.hsync_len = 4,
.upper_margin = 8,
.lower_margin = 7,
......@@ -272,7 +273,6 @@ static struct platform_device h1940_lcd_powerdev = {
};
static struct platform_device *h1940_devices[] __initdata = {
&s3c_device_ts,
&s3c_device_ohci,
&s3c_device_lcd,
&s3c_device_wdt,
......@@ -286,6 +286,8 @@ static struct platform_device *h1940_devices[] __initdata = {
&s3c_device_timer[0],
&h1940_backlight,
&h1940_lcd_powerdev,
&s3c_device_adc,
&s3c_device_ts,
};
static void __init h1940_map_io(void)
......@@ -339,7 +341,7 @@ static void __init h1940_init(void)
}
MACHINE_START(H1940, "IPAQ-H1940")
/* Maintainer: Ben Dooks <ben@fluff.org> */
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
......
......@@ -26,6 +26,7 @@
#include <linux/serial_core.h>
#include <linux/timer.h>
#include <linux/io.h>
#include <linux/mmc/host.h>
#include <mach/hardware.h>
#include <asm/irq.h>
......@@ -46,6 +47,7 @@
#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/mci.h>
#include <plat/s3c2410.h>
#include <plat/udc.h>
......@@ -172,8 +174,10 @@ static struct gpio_keys_button n35_buttons[] = {
{
.gpio = S3C2410_GPF(0),
.code = KEY_POWER,
.type = EV_PWR,
.desc = "Power",
.active_low = 0,
.wakeup = 1,
},
{
.gpio = S3C2410_GPG(9),
......@@ -264,6 +268,14 @@ static struct s3c24xx_led_platdata n30_blue_led_pdata = {
.def_trigger = "",
};
/* This is the blue LED on the device. Originaly used to indicate GPS activity
* by flashing. */
static struct s3c24xx_led_platdata n35_blue_led_pdata = {
.name = "blue_led",
.gpio = S3C2410_GPD(8),
.def_trigger = "",
};
/* This LED is driven by the battery microcontroller, and is blinking
* red, blinking green or solid green when the battery is low,
* charging or full respectively. By driving GPD9 low, it's possible
......@@ -275,6 +287,13 @@ static struct s3c24xx_led_platdata n30_warning_led_pdata = {
.def_trigger = "",
};
static struct s3c24xx_led_platdata n35_warning_led_pdata = {
.name = "warning_led",
.flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
.gpio = S3C2410_GPD(9),
.def_trigger = "",
};
static struct platform_device n30_blue_led = {
.name = "s3c24xx_led",
.id = 1,
......@@ -283,6 +302,14 @@ static struct platform_device n30_blue_led = {
},
};
static struct platform_device n35_blue_led = {
.name = "s3c24xx_led",
.id = 1,
.dev = {
.platform_data = &n35_blue_led_pdata,
},
};
static struct platform_device n30_warning_led = {
.name = "s3c24xx_led",
.id = 2,
......@@ -291,6 +318,14 @@ static struct platform_device n30_warning_led = {
},
};
static struct platform_device n35_warning_led = {
.name = "s3c24xx_led",
.id = 2,
.dev = {
.platform_data = &n35_warning_led_pdata,
},
};
static struct s3c2410fb_display n30_display __initdata = {
.type = S3C2410_LCDCON1_TFT,
.width = 240,
......@@ -317,13 +352,36 @@ static struct s3c2410fb_mach_info n30_fb_info __initdata = {
.lpcsel = 0x06,
};
static void n30_sdi_set_power(unsigned char power_mode, unsigned short vdd)
{
switch (power_mode) {
case MMC_POWER_ON:
case MMC_POWER_UP:
gpio_set_value(S3C2410_GPG(4), 1);
break;
case MMC_POWER_OFF:
default:
gpio_set_value(S3C2410_GPG(4), 0);
break;
}
}
static struct s3c24xx_mci_pdata n30_mci_cfg __initdata = {
.gpio_detect = S3C2410_GPF(1),
.gpio_wprotect = S3C2410_GPG(10),
.ocr_avail = MMC_VDD_32_33,
.set_power = n30_sdi_set_power,
};
static struct platform_device *n30_devices[] __initdata = {
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
&s3c_device_ohci,
&s3c_device_rtc,
&s3c_device_usbgadget,
&s3c_device_sdi,
&n30_button_device,
&n30_blue_led,
&n30_warning_led,
......@@ -334,8 +392,12 @@ static struct platform_device *n35_devices[] __initdata = {
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
&s3c_device_rtc,
&s3c_device_usbgadget,
&s3c_device_sdi,
&n35_button_device,
&n35_blue_led,
&n35_warning_led,
};
static struct s3c2410_platform_i2c __initdata n30_i2ccfg = {
......@@ -490,17 +552,15 @@ static void __init n30_map_io(void)
s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs));
}
static void __init n30_init_irq(void)
{
s3c24xx_init_irq();
}
/* GPB3 is the line that controls the pull-up for the USB D+ line */
static void __init n30_init(void)
{
WARN_ON(gpio_request(S3C2410_GPG(4), "mmc power"));
s3c24xx_fb_set_platdata(&n30_fb_info);
s3c24xx_udc_set_platdata(&n30_udc_cfg);
s3c24xx_mci_set_platdata(&n30_mci_cfg);
s3c_i2c0_set_platdata(&n30_i2ccfg);
/* Turn off suspend on both USB ports, and switch the
......@@ -532,7 +592,7 @@ static void __init n30_init(void)
s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
S3C2410_MISCCR_USBSUSPND0 |
S3C2410_MISCCR_USBSUSPND1,
S3C2410_MISCCR_USBSUSPND1);
S3C2410_MISCCR_USBSUSPND0);
platform_add_devices(n35_devices, ARRAY_SIZE(n35_devices));
}
......@@ -550,7 +610,7 @@ MACHINE_START(N30, "Acer-N30")
.boot_params = S3C2410_SDRAM_PA + 0x100,
.timer = &s3c24xx_timer,
.init_machine = n30_init,
.init_irq = n30_init_irq,
.init_irq = s3c24xx_init_irq,
.map_io = n30_map_io,
MACHINE_END
......@@ -562,6 +622,6 @@ MACHINE_START(N35, "Acer-N35")
.boot_params = S3C2410_SDRAM_PA + 0x100,
.timer = &s3c24xx_timer,
.init_machine = n30_init,
.init_irq = n30_init_irq,
.init_irq = s3c24xx_init_irq,
.map_io = n30_map_io,
MACHINE_END
......@@ -60,10 +60,10 @@ static void s3c2410_pm_prepare(void)
__raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
}
/* the RX3715 uses similar code and the same H1940 and the
/* RX3715 and RX1950 use similar to H1940 code and the
* same offsets for resume and checksum pointers */
if (machine_is_rx3715()) {
if (machine_is_rx3715() || machine_is_rx1950()) {
void *base = phys_to_virt(H1940_SUSPEND_CHECK);
unsigned long ptr;
unsigned long calc = 0;
......@@ -79,6 +79,17 @@ static void s3c2410_pm_prepare(void)
if ( machine_is_aml_m5900() )
s3c2410_gpio_setpin(S3C2410_GPF(2), 1);
if (machine_is_rx1950()) {
/* According to S3C2442 user's manual, page 7-17,
* when the system is operating in NAND boot mode,
* the hardware pin configuration - EINT[23:21] –
* must be set as input for starting up after
* wakeup from sleep mode
*/
s3c_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPIO_INPUT);
s3c_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPIO_INPUT);
s3c_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPIO_INPUT);
}
}
static int s3c2410_pm_resume(struct sys_device *dev)
......
......@@ -16,41 +16,43 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <plat/gpio-core.h>
int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state)
{
void __iomem *base = S3C24XX_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
unsigned long offs = pin - chip->chip.base;
unsigned long flags;
unsigned long slpcon;
offs *= 2;
if (pin < S3C2410_GPIO_BANKB)
if (pin < S3C2410_GPB(0))
return -EINVAL;
if (pin >= S3C2410_GPIO_BANKF &&
pin <= S3C2410_GPIO_BANKG)
if (pin >= S3C2410_GPF(0) &&
pin <= S3C2410_GPG(16))
return -EINVAL;
if (pin > (S3C2410_GPIO_BANKH + 32))
if (pin > S3C2410_GPH(16))
return -EINVAL;
local_irq_save(flags);
slpcon = __raw_readl(base + 0x0C);
slpcon = __raw_readl(chip->base + 0x0C);
slpcon &= ~(3 << offs);
slpcon |= state << offs;
__raw_writel(slpcon, base + 0x0C);
__raw_writel(slpcon, chip->base + 0x0C);
local_irq_restore(flags);
......
......@@ -674,7 +674,7 @@ static void __init jive_machine_init(void)
}
MACHINE_START(JIVE, "JIVE")
/* Maintainer: Ben Dooks <ben@fluff.org> */
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
......
......@@ -150,7 +150,7 @@ static void __init smdk2413_machine_init(void)
}
MACHINE_START(S3C2413, "S3C2413")
/* Maintainer: Ben Dooks <ben@fluff.org> */
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
......@@ -163,7 +163,7 @@ MACHINE_START(S3C2413, "S3C2413")
MACHINE_END
MACHINE_START(SMDK2412, "SMDK2412")
/* Maintainer: Ben Dooks <ben@fluff.org> */
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
......@@ -176,7 +176,7 @@ MACHINE_START(SMDK2412, "SMDK2412")
MACHINE_END
MACHINE_START(SMDK2413, "SMDK2413")
/* Maintainer: Ben Dooks <ben@fluff.org> */
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
......
......@@ -30,6 +30,7 @@ menu "S3C2416 Machines"
config MACH_SMDK2416
bool "SMDK2416"
select CPU_S3C2416
select S3C_DEV_FB
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
help
......
......@@ -22,6 +22,7 @@
#include <linux/io.h>
#include <linux/mtd/partitions.h>
#include <linux/gpio.h>
#include <linux/fb.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
......@@ -36,16 +37,19 @@
#include <mach/regs-lcd.h>
#include <mach/idle.h>
#include <mach/fb.h>
#include <mach/leds-gpio.h>
#include <plat/iic.h>
#include <plat/s3c2416.h>
#include <plat/gpio-cfg.h>
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/nand.h>
#include <plat/regs-fb-v4.h>
#include <plat/fb.h>
#include <plat/common-smdk.h>
static struct map_desc smdk2416_iodesc[] __initdata = {
......@@ -109,7 +113,54 @@ static struct s3c2410_uartcfg smdk2416_uartcfgs[] __initdata = {
}
};
struct s3c_fb_pd_win smdk2416_fb_win[] = {
[0] = {
/* think this is the same as the smdk6410 */
.win_mode = {
.pixclock = 41094,
.left_margin = 8,
.right_margin = 13,
.upper_margin = 7,
.lower_margin = 5,
.hsync_len = 3,
.vsync_len = 1,
.xres = 800,
.yres = 480,
},
.default_bpp = 16,
.max_bpp = 32,
},
};
static void s3c2416_fb_gpio_setup_24bpp(void)
{
unsigned int gpio;
for (gpio = S3C2410_GPC(1); gpio <= S3C2410_GPC(4); gpio++) {
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
for (gpio = S3C2410_GPC(8); gpio <= S3C2410_GPC(15); gpio++) {
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
for (gpio = S3C2410_GPD(0); gpio <= S3C2410_GPD(15); gpio++) {
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
}
static struct s3c_fb_platdata smdk2416_fb_platdata = {
.win[0] = &smdk2416_fb_win[0],
.setup_gpio = s3c2416_fb_gpio_setup_24bpp,
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
};
static struct platform_device *smdk2416_devices[] __initdata = {
&s3c_device_fb,
&s3c_device_wdt,
&s3c_device_ohci,
&s3c_device_i2c0,
......@@ -119,20 +170,25 @@ static struct platform_device *smdk2416_devices[] __initdata = {
static void __init smdk2416_map_io(void)
{
s3c24xx_init_io(smdk2416_iodesc, ARRAY_SIZE(smdk2416_iodesc));
s3c24xx_init_clocks(12000000);
s3c24xx_init_uarts(smdk2416_uartcfgs, ARRAY_SIZE(smdk2416_uartcfgs));
}
static void __init smdk2416_machine_init(void)
{
s3c_i2c0_set_platdata(NULL);
s3c_fb_set_platdata(&smdk2416_fb_platdata);
gpio_request(S3C2410_GPB(4), "USBHost Power");
gpio_direction_output(S3C2410_GPB(4), 1);
gpio_request(S3C2410_GPB(3), "Display Power");
gpio_direction_output(S3C2410_GPB(3), 1);
gpio_request(S3C2410_GPB(1), "Display Reset");
gpio_direction_output(S3C2410_GPB(1), 1);
platform_add_devices(smdk2416_devices, ARRAY_SIZE(smdk2416_devices));
smdk_machine_init();
}
......
......@@ -90,6 +90,8 @@ int __init s3c2416_init(void)
s3c_i2c0_setname("s3c2440-i2c");
s3c_i2c1_setname("s3c2440-i2c");
s3c_device_fb.name = "s3c2443-fb";
return sysdev_register(&s3c2416_sysdev);
}
......
......@@ -188,4 +188,17 @@ config MACH_MINI2440
Say Y here to select support for the MINI2440. Is a 10cm x 10cm board
available via various sources. It can come with a 3.5" or 7" touch LCD.
config MACH_RX1950
bool "HP iPAQ rx1950"
select CPU_S3C2442
select S3C24XX_DCLK
select PM_H1940 if PM
select I2C
select S3C2410_PWM
select S3C_DEV_NAND
select S3C2410_IOTIMING if S3C2440_CPUFREQ
select S3C2440_XTAL_16934400
help
Say Y here if you're using HP iPAQ rx1950
endmenu
......@@ -34,6 +34,7 @@ obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o
obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o
obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o
obj-$(CONFIG_MACH_RX1950) += mach-rx1950.o
# extra machine support
......
/* linux/arch/arm/mach-s3c2440/mach-rx1950.c
*
* Copyright (c) 2006-2009 Victor Chukhantsev, Denis Grigoriev,
* Copyright (c) 2007-2010 Vasily Khoruzhick
*
* based on smdk2440 written by Ben Dooks
*
* 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/delay.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/sysdev.h>
#include <linux/pwm_backlight.h>
#include <linux/pwm.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mmc/host.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach-types.h>
#include <mach/regs-gpio.h>
#include <mach/regs-gpioj.h>
#include <mach/h1940.h>
#include <mach/fb.h>
#include <plat/clock.h>
#include <plat/regs-serial.h>
#include <plat/regs-iic.h>
#include <plat/mci.h>
#include <plat/udc.h>
#include <plat/nand.h>
#include <plat/iic.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/pm.h>
#include <plat/irq.h>
#include <plat/ts.h>
#define LCD_PWM_PERIOD 192960
#define LCD_PWM_DUTY 127353
static struct map_desc rx1950_iodesc[] __initdata = {
};
static struct s3c24xx_uart_clksrc rx1950_serial_clocks[] = {
[0] = {
.name = "fclk",
.divisor = 0x0a,
.min_baud = 0,
.max_baud = 0,
},
};
static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
.flags = 0,
.ucon = 0x3c5,
.ulcon = 0x03,
.ufcon = 0x51,
.clocks = rx1950_serial_clocks,
.clocks_size = ARRAY_SIZE(rx1950_serial_clocks),
},
[1] = {
.hwport = 1,
.flags = 0,
.ucon = 0x3c5,
.ulcon = 0x03,
.ufcon = 0x51,
.clocks = rx1950_serial_clocks,
.clocks_size = ARRAY_SIZE(rx1950_serial_clocks),
},
/* IR port */
[2] = {
.hwport = 2,
.flags = 0,
.ucon = 0x3c5,
.ulcon = 0x43,
.ufcon = 0xf1,
.clocks = rx1950_serial_clocks,
.clocks_size = ARRAY_SIZE(rx1950_serial_clocks),
},
};
static struct s3c2410fb_display rx1950_display = {
.type = S3C2410_LCDCON1_TFT,
.width = 240,
.height = 320,
.xres = 240,
.yres = 320,
.bpp = 16,
.pixclock = 260000,
.left_margin = 10,
.right_margin = 20,
.hsync_len = 10,
.upper_margin = 2,
.lower_margin = 2,
.vsync_len = 2,
.lcdcon5 = S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVCLK |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
S3C2410_LCDCON5_HWSWP |
(0x02 << 13) |
(0x02 << 15),
};
static struct s3c2410fb_mach_info rx1950_lcd_cfg = {
.displays = &rx1950_display,
.num_displays = 1,
.default_display = 0,
.lpcsel = 0x02,
.gpccon = 0xaa9556a9,
.gpccon_mask = 0xffc003fc,
.gpcup = 0x0000ffff,
.gpcup_mask = 0xffffffff,
.gpdcon = 0xaa90aaa1,
.gpdcon_mask = 0xffc0fff0,
.gpdup = 0x0000fcfd,
.gpdup_mask = 0xffffffff,
};
static struct pwm_device *lcd_pwm;
void rx1950_lcd_power(int enable)
{
int i;
static int enabled;
if (enabled == enable)
return;
if (!enable) {
/* GPC11-GPC15->OUTPUT */
for (i = 11; i < 16; i++)
gpio_direction_output(S3C2410_GPC(i), 1);
/* Wait a bit here... */
mdelay(100);
/* GPD2-GPD7->OUTPUT */
/* GPD11-GPD15->OUTPUT */
/* GPD2-GPD7->1, GPD11-GPD15->1 */
for (i = 2; i < 8; i++)
gpio_direction_output(S3C2410_GPD(i), 1);
for (i = 11; i < 16; i++)
gpio_direction_output(S3C2410_GPD(i), 1);
/* Wait a bit here...*/
mdelay(100);
/* GPB0->OUTPUT, GPB0->0 */
gpio_direction_output(S3C2410_GPB(0), 0);
/* GPC1-GPC4->OUTPUT, GPC1-4->0 */
for (i = 1; i < 5; i++)
gpio_direction_output(S3C2410_GPC(i), 0);
/* GPC15-GPC11->0 */
for (i = 11; i < 16; i++)
gpio_direction_output(S3C2410_GPC(i), 0);
/* GPD15-GPD11->0, GPD2->GPD7->0 */
for (i = 11; i < 16; i++)
gpio_direction_output(S3C2410_GPD(i), 0);
for (i = 2; i < 8; i++)
gpio_direction_output(S3C2410_GPD(i), 0);
/* GPC6->0, GPC7->0, GPC5->0 */
gpio_direction_output(S3C2410_GPC(6), 0);
gpio_direction_output(S3C2410_GPC(7), 0);
gpio_direction_output(S3C2410_GPC(5), 0);
/* GPB1->OUTPUT, GPB1->0 */
gpio_direction_output(S3C2410_GPB(1), 0);
pwm_config(lcd_pwm, 0, LCD_PWM_PERIOD);
pwm_disable(lcd_pwm);
/* GPC0->0, GPC10->0 */
gpio_direction_output(S3C2410_GPC(0), 0);
gpio_direction_output(S3C2410_GPC(10), 0);
} else {
pwm_config(lcd_pwm, LCD_PWM_DUTY, LCD_PWM_PERIOD);
pwm_enable(lcd_pwm);
gpio_direction_output(S3C2410_GPC(0), 1);
gpio_direction_output(S3C2410_GPC(5), 1);
s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPB1_TOUT1);
gpio_direction_output(S3C2410_GPC(7), 1);
for (i = 1; i < 5; i++)
s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2));
for (i = 11; i < 16; i++)
s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2));
for (i = 2; i < 8; i++)
s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2));
for (i = 11; i < 16; i++)
s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2));
gpio_direction_output(S3C2410_GPC(10), 1);
gpio_direction_output(S3C2410_GPC(6), 1);
}
enabled = enable;
}
static void rx1950_bl_power(int enable)
{
static int enabled;
if (enabled == enable)
return;
if (!enable) {
gpio_direction_output(S3C2410_GPB(0), 0);
} else {
/* LED driver need a "push" to power on */
gpio_direction_output(S3C2410_GPB(0), 1);
/* Warm up backlight for one period of PWM.
* Without this trick its almost impossible to
* enable backlight with low brightness value
*/
ndelay(48000);
s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
}
enabled = enable;
}
static int rx1950_backlight_init(struct device *dev)
{
WARN_ON(gpio_request(S3C2410_GPB(0), "Backlight"));
lcd_pwm = pwm_request(1, "RX1950 LCD");
if (IS_ERR(lcd_pwm)) {
dev_err(dev, "Unable to request PWM for LCD power!\n");
return PTR_ERR(lcd_pwm);
}
rx1950_lcd_power(1);
rx1950_bl_power(1);
return 0;
}
static void rx1950_backlight_exit(struct device *dev)
{
rx1950_bl_power(0);
rx1950_lcd_power(0);
pwm_free(lcd_pwm);
gpio_free(S3C2410_GPB(0));
}
static int rx1950_backlight_notify(struct device *dev, int brightness)
{
if (!brightness) {
rx1950_bl_power(0);
rx1950_lcd_power(0);
} else {
rx1950_lcd_power(1);
rx1950_bl_power(1);
}
return brightness;
}
static struct platform_pwm_backlight_data rx1950_backlight_data = {
.pwm_id = 0,
.max_brightness = 24,
.dft_brightness = 4,
.pwm_period_ns = 48000,
.init = rx1950_backlight_init,
.notify = rx1950_backlight_notify,
.exit = rx1950_backlight_exit,
};
static struct platform_device rx1950_backlight = {
.name = "pwm-backlight",
.dev = {
.parent = &s3c_device_timer[0].dev,
.platform_data = &rx1950_backlight_data,
},
};
static void rx1950_set_mmc_power(unsigned char power_mode, unsigned short vdd)
{
switch (power_mode) {
case MMC_POWER_OFF:
gpio_direction_output(S3C2410_GPJ(1), 0);
break;
case MMC_POWER_UP:
case MMC_POWER_ON:
gpio_direction_output(S3C2410_GPJ(1), 1);
break;
default:
break;
}
}
static struct s3c24xx_mci_pdata rx1950_mmc_cfg __initdata = {
.gpio_detect = S3C2410_GPF(5),
.gpio_wprotect = S3C2410_GPH(8),
.set_power = rx1950_set_mmc_power,
.ocr_avail = MMC_VDD_32_33,
};
static struct mtd_partition rx1950_nand_part[] = {
[0] = {
.name = "Boot0",
.offset = 0,
.size = 0x4000,
.mask_flags = MTD_WRITEABLE,
},
[1] = {
.name = "Boot1",
.offset = MTDPART_OFS_APPEND,
.size = 0x40000,
.mask_flags = MTD_WRITEABLE,
},
[2] = {
.name = "Kernel",
.offset = MTDPART_OFS_APPEND,
.size = 0x300000,
.mask_flags = 0,
},
[3] = {
.name = "Filesystem",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
.mask_flags = 0,
},
};
static struct s3c2410_nand_set rx1950_nand_sets[] = {
[0] = {
.name = "Internal",
.nr_chips = 1,
.nr_partitions = ARRAY_SIZE(rx1950_nand_part),
.partitions = rx1950_nand_part,
},
};
static struct s3c2410_platform_nand rx1950_nand_info = {
.tacls = 25,
.twrph0 = 50,
.twrph1 = 15,
.nr_sets = ARRAY_SIZE(rx1950_nand_sets),
.sets = rx1950_nand_sets,
};
static void rx1950_udc_pullup(enum s3c2410_udc_cmd_e cmd)
{
switch (cmd) {
case S3C2410_UDC_P_ENABLE:
gpio_direction_output(S3C2410_GPJ(5), 1);
break;
case S3C2410_UDC_P_DISABLE:
gpio_direction_output(S3C2410_GPJ(5), 0);
break;
case S3C2410_UDC_P_RESET:
break;
default:
break;
}
}
static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
.udc_command = rx1950_udc_pullup,
.vbus_pin = S3C2410_GPG(5),
.vbus_pin_inverted = 1,
};
static struct s3c2410_ts_mach_info rx1950_ts_cfg __initdata = {
.delay = 10000,
.presc = 49,
.oversampling_shift = 3,
};
static struct gpio_keys_button rx1950_gpio_keys_table[] = {
{
.code = KEY_POWER,
.gpio = S3C2410_GPF(0),
.active_low = 1,
.desc = "Power button",
.wakeup = 1,
},
{
.code = KEY_F5,
.gpio = S3C2410_GPF(7),
.active_low = 1,
.desc = "Record button",
},
{
.code = KEY_F1,
.gpio = S3C2410_GPG(0),
.active_low = 1,
.desc = "Calendar button",
},
{
.code = KEY_F2,
.gpio = S3C2410_GPG(2),
.active_low = 1,
.desc = "Contacts button",
},
{
.code = KEY_F3,
.gpio = S3C2410_GPG(3),
.active_low = 1,
.desc = "Mail button",
},
{
.code = KEY_F4,
.gpio = S3C2410_GPG(7),
.active_low = 1,
.desc = "WLAN button",
},
{
.code = KEY_LEFT,
.gpio = S3C2410_GPG(10),
.active_low = 1,
.desc = "Left button",
},
{
.code = KEY_RIGHT,
.gpio = S3C2410_GPG(11),
.active_low = 1,
.desc = "Right button",
},
{
.code = KEY_UP,
.gpio = S3C2410_GPG(4),
.active_low = 1,
.desc = "Up button",
},
{
.code = KEY_DOWN,
.gpio = S3C2410_GPG(6),
.active_low = 1,
.desc = "Down button",
},
{
.code = KEY_ENTER,
.gpio = S3C2410_GPG(9),
.active_low = 1,
.desc = "Ok button"
},
};
static struct gpio_keys_platform_data rx1950_gpio_keys_data = {
.buttons = rx1950_gpio_keys_table,
.nbuttons = ARRAY_SIZE(rx1950_gpio_keys_table),
};
static struct platform_device rx1950_device_gpiokeys = {
.name = "gpio-keys",
.dev.platform_data = &rx1950_gpio_keys_data,
};
static struct s3c2410_platform_i2c rx1950_i2c_data = {
.flags = 0,
.slave_addr = 0x42,
.frequency = 400 * 1000,
.sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON,
};
static struct platform_device *rx1950_devices[] __initdata = {
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
&s3c_device_usbgadget,
&s3c_device_rtc,
&s3c_device_nand,
&s3c_device_sdi,
&s3c_device_adc,
&s3c_device_ts,
&s3c_device_timer[0],
&s3c_device_timer[1],
&rx1950_backlight,
&rx1950_device_gpiokeys,
};
static struct clk *rx1950_clocks[] __initdata = {
&s3c24xx_clkout0,
&s3c24xx_clkout1,
};
static void __init rx1950_map_io(void)
{
s3c24xx_clkout0.parent = &clk_h;
s3c24xx_clkout1.parent = &clk_f;
s3c24xx_register_clocks(rx1950_clocks, ARRAY_SIZE(rx1950_clocks));
s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc));
s3c24xx_init_clocks(16934000);
s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs));
/* setup PM */
#ifdef CONFIG_PM_H1940
memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 8);
#endif
s3c_pm_init();
}
static void __init rx1950_init_machine(void)
{
int i;
s3c24xx_fb_set_platdata(&rx1950_lcd_cfg);
s3c24xx_udc_set_platdata(&rx1950_udc_cfg);
s3c24xx_ts_set_platdata(&rx1950_ts_cfg);
s3c24xx_mci_set_platdata(&rx1950_mmc_cfg);
s3c_i2c0_set_platdata(&rx1950_i2c_data);
s3c_nand_set_platdata(&rx1950_nand_info);
/* Turn off suspend on both USB ports, and switch the
* selectable USB port to USB device mode. */
s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
S3C2410_MISCCR_USBSUSPND0 |
S3C2410_MISCCR_USBSUSPND1, 0x0);
WARN_ON(gpio_request(S3C2410_GPJ(5), "UDC pullup"));
gpio_direction_output(S3C2410_GPJ(5), 0);
/* mmc power is disabled by default */
WARN_ON(gpio_request(S3C2410_GPJ(1), "MMC power"));
gpio_direction_output(S3C2410_GPJ(1), 0);
for (i = 0; i < 8; i++)
WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power"));
for (i = 10; i < 16; i++)
WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power"));
for (i = 2; i < 8; i++)
WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power"));
for (i = 11; i < 16; i++)
WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power"));
WARN_ON(gpio_request(S3C2410_GPB(1), "LCD power"));
platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices));
}
MACHINE_START(RX1950, "HP iPAQ RX1950")
/* Maintainers: Vasily Khoruzhick */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32) S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = rx1950_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = rx1950_init_machine,
.timer = &s3c24xx_timer,
MACHINE_END
......@@ -209,7 +209,7 @@ static void __init rx3715_init_machine(void)
}
MACHINE_START(RX3715, "IPAQ-RX3715")
/* Maintainer: Ben Dooks <ben@fluff.org> */
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
......
......@@ -174,7 +174,7 @@ static void __init smdk2440_machine_init(void)
}
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks <ben@fluff.org> */
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
......
......@@ -131,7 +131,7 @@ static void __init smdk2443_machine_init(void)
}
MACHINE_START(SMDK2443, "SMDK2443")
/* Maintainer: Ben Dooks <ben@fluff.org> */
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
......
......@@ -85,6 +85,7 @@ config MACH_ANW6410
config MACH_SMDK6410
bool "SMDK6410"
select CPU_S3C6410
select SAMSUNG_DEV_ADC
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_I2C1
......
......@@ -56,7 +56,6 @@ obj-$(CONFIG_MACH_HMT) += mach-hmt.o
# device support
obj-y += dev-uart.o
obj-y += dev-rtc.o
obj-y += dev-audio.o
obj-$(CONFIG_S3C_ADC) += dev-adc.o
obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
obj-$(CONFIG_S3C64XX_DEV_TS) += dev-ts.o
......@@ -88,6 +88,12 @@ struct clk clk_48m = {
.enable = clk_48m_ctrl,
};
struct clk clk_xusbxti = {
.name = "xusbxti",
.id = -1,
.rate = 48000000,
};
static int inline s3c64xx_gate(void __iomem *reg,
struct clk *clk,
int enable)
......@@ -518,6 +524,11 @@ static struct clk clk_iis_cd1 = {
.id = -1,
};
static struct clk clk_iisv4_cd = {
.name = "iis_cdclk_v4",
.id = -1,
};
static struct clk clk_pcm_cd = {
.name = "pcm_cdclk",
.id = -1,
......@@ -549,6 +560,19 @@ static struct clksrc_sources clkset_audio1 = {
.nr_sources = ARRAY_SIZE(clkset_audio1_list),
};
static struct clk *clkset_audio2_list[] = {
[0] = &clk_mout_epll.clk,
[1] = &clk_dout_mpll,
[2] = &clk_fin_epll,
[3] = &clk_iisv4_cd,
[4] = &clk_pcm_cd,
};
static struct clksrc_sources clkset_audio2 = {
.sources = clkset_audio2_list,
.nr_sources = ARRAY_SIZE(clkset_audio2_list),
};
static struct clk *clkset_camif_list[] = {
&clk_h2,
};
......@@ -650,6 +674,16 @@ static struct clksrc_clk clksrcs[] = {
.reg_src = { .reg = S3C_CLK_SRC, .shift = 10, .size = 3 },
.reg_div = { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4 },
.sources = &clkset_audio1,
}, {
.clk = {
.name = "audio-bus",
.id = -1, /* There's only one IISv4 port */
.ctrlbit = S3C6410_CLKCON_SCLK_AUDIO2,
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C6410_CLK_SRC2, .shift = 0, .size = 3 },
.reg_div = { .reg = S3C_CLK_DIV2, .shift = 24, .size = 4 },
.sources = &clkset_audio2,
}, {
.clk = {
.name = "irda-bus",
......@@ -749,6 +783,7 @@ static struct clk *clks1[] __initdata = {
&clk_ext_xtal_mux,
&clk_iis_cd0,
&clk_iis_cd1,
&clk_iisv4_cd,
&clk_pcm_cd,
&clk_mout_epll.clk,
&clk_mout_mpll.clk,
......@@ -762,6 +797,7 @@ static struct clk *clks[] __initdata = {
&clk_27m,
&clk_48m,
&clk_h2,
&clk_xusbxti,
};
/**
......
......@@ -414,7 +414,7 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
EXPORT_SYMBOL(s3c2410_dma_enqueue);
int s3c2410_dma_devconfig(int channel,
int s3c2410_dma_devconfig(unsigned int channel,
enum s3c2410_dmasrc source,
unsigned long devaddr)
{
......
......@@ -103,5 +103,8 @@
#define S3C_PA_USBHOST S3C64XX_PA_USBHOST
#define S3C_PA_USB_HSOTG S3C64XX_PA_USB_HSOTG
#define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY
#define S3C_PA_RTC S3C64XX_PA_RTC
#define SAMSUNG_PA_ADC S3C64XX_PA_ADC
#endif /* __ASM_ARCH_6400_MAP_H */
......@@ -33,6 +33,7 @@
#define S3C_PCLK_GATE S3C_CLKREG(0x34)
#define S3C_SCLK_GATE S3C_CLKREG(0x38)
#define S3C_MEM0_GATE S3C_CLKREG(0x3C)
#define S3C6410_CLK_SRC2 S3C_CLKREG(0x10C)
/* CLKDIV0 */
#define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12)
......
......@@ -84,7 +84,7 @@ static void __init smdk6400_machine_init(void)
}
MACHINE_START(SMDK6400, "SMDK6400")
/* Maintainer: Ben Dooks <ben@fluff.org> */
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
......
......@@ -656,7 +656,7 @@ static void __init smdk6410_machine_init(void)
}
MACHINE_START(SMDK6410, "SMDK6410")
/* Maintainer: Ben Dooks <ben@fluff.org> */
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
......
......@@ -38,6 +38,7 @@
#include <plat/clock.h>
#include <plat/sdhci.h>
#include <plat/iic-core.h>
#include <plat/adc.h>
#include <mach/s3c6400.h>
#include <mach/s3c6410.h>
......@@ -52,6 +53,7 @@ void __init s3c6410_map_io(void)
s3c_i2c0_setname("s3c2440-i2c");
s3c_i2c1_setname("s3c2440-i2c");
s3c_device_adc.name = "s3c64xx-adc";
s3c_device_nand.name = "s3c6400-nand";
}
......
......@@ -9,6 +9,7 @@ if ARCH_S5P6440
config CPU_S5P6440
bool
select S3C_PL330_DMA
help
Enable S5P6440 CPU support
......
......@@ -12,8 +12,12 @@ obj- :=
# Core support for S5P6440 system
obj-$(CONFIG_CPU_S5P6440) += cpu.o init.o clock.o gpio.o
obj-$(CONFIG_CPU_S5P6440) += cpu.o init.o clock.o gpio.o dma.o
obj-$(CONFIG_CPU_S5P6440) += setup-i2c0.o
# machine support
obj-$(CONFIG_MACH_SMDK6440) += mach-smdk6440.o
# device support
obj-y += dev-audio.o
......@@ -134,24 +134,6 @@ static struct clksrc_clk clk_mout_mpll = {
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 },
};
static struct clk clk_h_low = {
.name = "hclk_low",
.id = -1,
.rate = 0,
.parent = NULL,
.ctrlbit = 0,
.ops = &clk_ops_def_setrate,
};
static struct clk clk_p_low = {
.name = "pclk_low",
.id = -1,
.rate = 0,
.parent = NULL,
.ctrlbit = 0,
.ops = &clk_ops_def_setrate,
};
enum perf_level {
L0 = 532*1000,
L1 = 266*1000,
......@@ -247,23 +229,70 @@ static struct clk_ops s5p6440_clkarm_ops = {
.round_rate = s5p6440_armclk_round_rate,
};
static unsigned long s5p6440_clk_doutmpll_get_rate(struct clk *clk)
{
unsigned long rate = clk_get_rate(clk->parent);
static struct clksrc_clk clk_armclk = {
.clk = {
.name = "armclk",
.id = 1,
.parent = &clk_mout_apll.clk,
.ops = &s5p6440_clkarm_ops,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 4 },
};
if (__raw_readl(S5P_CLK_DIV0) & S5P_CLKDIV0_MPLL_MASK)
rate /= 2;
static struct clksrc_clk clk_dout_mpll = {
.clk = {
.name = "dout_mpll",
.id = -1,
.parent = &clk_mout_mpll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 },
};
return rate;
}
static struct clksrc_clk clk_hclk = {
.clk = {
.name = "clk_hclk",
.id = -1,
.parent = &clk_armclk.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 },
};
static struct clk clk_dout_mpll = {
.name = "dout_mpll",
.id = -1,
.parent = &clk_mout_mpll.clk,
.ops = &(struct clk_ops) {
.get_rate = s5p6440_clk_doutmpll_get_rate,
static struct clksrc_clk clk_pclk = {
.clk = {
.name = "clk_pclk",
.id = -1,
.parent = &clk_hclk.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 4 },
};
static struct clk *clkset_hclklow_list[] = {
&clk_mout_apll.clk,
&clk_mout_mpll.clk,
};
static struct clksrc_sources clkset_hclklow = {
.sources = clkset_hclklow_list,
.nr_sources = ARRAY_SIZE(clkset_hclklow_list),
};
static struct clksrc_clk clk_hclk_low = {
.clk = {
.name = "hclk_low",
.id = -1,
},
.sources = &clkset_hclklow,
.reg_src = { .reg = S5P_SYS_OTHERS, .shift = 6, .size = 1 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
};
static struct clksrc_clk clk_pclk_low = {
.clk = {
.name = "pclk_low",
.id = -1,
.parent = &clk_hclk_low.clk,
},
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
};
int s5p6440_clk48m_ctrl(struct clk *clk, int enable)
......@@ -307,6 +336,11 @@ static int s5p6440_sclk_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable);
}
static int s5p6440_sclk1_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLK_GATE_SCLK1, clk, enable);
}
static int s5p6440_mem_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable);
......@@ -321,37 +355,37 @@ static struct clk init_clocks_disable[] = {
{
.name = "nand",
.id = -1,
.parent = &clk_h,
.parent = &clk_hclk.clk,
.enable = s5p6440_mem_ctrl,
.ctrlbit = S5P_CLKCON_MEM0_HCLK_NFCON,
}, {
.name = "adc",
.id = -1,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_TSADC,
}, {
.name = "i2c",
.id = -1,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_IIC0,
}, {
.name = "i2s_v40",
.id = 0,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_IIS2,
}, {
.name = "spi",
.id = 0,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_SPI0,
}, {
.name = "spi",
.id = 1,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_SPI1,
}, {
......@@ -387,58 +421,124 @@ static struct clk init_clocks_disable[] = {
}, {
.name = "otg",
.id = -1,
.parent = &clk_h_low,
.parent = &clk_hclk_low.clk,
.enable = s5p6440_hclk0_ctrl,
.ctrlbit = S5P_CLKCON_HCLK0_USB
}, {
.name = "post",
.id = -1,
.parent = &clk_h_low,
.parent = &clk_hclk_low.clk,
.enable = s5p6440_hclk0_ctrl,
.ctrlbit = S5P_CLKCON_HCLK0_POST0
}, {
.name = "lcd",
.id = -1,
.parent = &clk_h_low,
.parent = &clk_hclk_low.clk,
.enable = s5p6440_hclk1_ctrl,
.ctrlbit = S5P_CLKCON_HCLK1_DISPCON,
}, {
.name = "hsmmc",
.id = 0,
.parent = &clk_h_low,
.parent = &clk_hclk_low.clk,
.enable = s5p6440_hclk0_ctrl,
.ctrlbit = S5P_CLKCON_HCLK0_HSMMC0,
}, {
.name = "hsmmc",
.id = 1,
.parent = &clk_h_low,
.parent = &clk_hclk_low.clk,
.enable = s5p6440_hclk0_ctrl,
.ctrlbit = S5P_CLKCON_HCLK0_HSMMC1,
}, {
.name = "hsmmc",
.id = 2,
.parent = &clk_h_low,
.parent = &clk_hclk_low.clk,
.enable = s5p6440_hclk0_ctrl,
.ctrlbit = S5P_CLKCON_HCLK0_HSMMC2,
}, {
.name = "rtc",
.id = -1,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_RTC,
}, {
.name = "watchdog",
.id = -1,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_WDT,
}, {
.name = "timers",
.id = -1,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_PWM,
}
}, {
.name = "hclk_fimgvg",
.id = -1,
.parent = &clk_hclk.clk,
.enable = s5p6440_hclk1_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "tsi",
.id = -1,
.parent = &clk_hclk_low.clk,
.enable = s5p6440_hclk1_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "pclk_fimgvg",
.id = -1,
.parent = &clk_pclk.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = (1 << 31),
}, {
.name = "dmc0",
.id = -1,
.parent = &clk_pclk.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = (1 << 30),
}, {
.name = "etm",
.id = -1,
.parent = &clk_pclk.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = (1 << 29),
}, {
.name = "dsim",
.id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = (1 << 28),
}, {
.name = "gps",
.id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = (1 << 25),
}, {
.name = "pcm",
.id = -1,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "irom",
.id = -1,
.parent = &clk_hclk.clk,
.enable = s5p6440_hclk0_ctrl,
.ctrlbit = (1 << 25),
}, {
.name = "dma",
.id = -1,
.parent = &clk_hclk_low.clk,
.enable = s5p6440_hclk0_ctrl,
.ctrlbit = (1 << 12),
}, {
.name = "2d",
.id = -1,
.parent = &clk_hclk.clk,
.enable = s5p6440_hclk0_ctrl,
.ctrlbit = (1 << 8),
},
};
/*
......@@ -448,34 +548,46 @@ static struct clk init_clocks[] = {
{
.name = "gpio",
.id = -1,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_GPIO,
}, {
.name = "uart",
.id = 0,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_UART0,
}, {
.name = "uart",
.id = 1,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_UART1,
}, {
.name = "uart",
.id = 2,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_UART2,
}, {
.name = "uart",
.id = 3,
.parent = &clk_p_low,
.parent = &clk_pclk_low.clk,
.enable = s5p6440_pclk_ctrl,
.ctrlbit = S5P_CLKCON_PCLK_UART3,
}
}, {
.name = "mem",
.id = -1,
.parent = &clk_hclk.clk,
.enable = s5p6440_hclk0_ctrl,
.ctrlbit = (1 << 21),
}, {
.name = "intc",
.id = -1,
.parent = &clk_hclk.clk,
.enable = s5p6440_hclk0_ctrl,
.ctrlbit = (1 << 1),
},
};
static struct clk clk_iis_cd_v40 = {
......@@ -488,20 +600,20 @@ static struct clk clk_pcm_cd = {
.id = -1,
};
static struct clk *clkset_spi_mmc_list[] = {
static struct clk *clkset_group1_list[] = {
&clk_mout_epll.clk,
&clk_dout_mpll,
&clk_dout_mpll.clk,
&clk_fin_epll,
};
static struct clksrc_sources clkset_spi_mmc = {
.sources = clkset_spi_mmc_list,
.nr_sources = ARRAY_SIZE(clkset_spi_mmc_list),
static struct clksrc_sources clkset_group1 = {
.sources = clkset_group1_list,
.nr_sources = ARRAY_SIZE(clkset_group1_list),
};
static struct clk *clkset_uart_list[] = {
&clk_mout_epll.clk,
&clk_dout_mpll
&clk_dout_mpll.clk,
};
static struct clksrc_sources clkset_uart = {
......@@ -509,6 +621,19 @@ static struct clksrc_sources clkset_uart = {
.nr_sources = ARRAY_SIZE(clkset_uart_list),
};
static struct clk *clkset_audio_list[] = {
&clk_mout_epll.clk,
&clk_dout_mpll.clk,
&clk_fin_epll,
&clk_iis_cd_v40,
&clk_pcm_cd,
};
static struct clksrc_sources clkset_audio = {
.sources = clkset_audio_list,
.nr_sources = ARRAY_SIZE(clkset_audio_list),
};
static struct clksrc_clk clksrcs[] = {
{
.clk = {
......@@ -517,7 +642,7 @@ static struct clksrc_clk clksrcs[] = {
.ctrlbit = S5P_CLKCON_SCLK0_MMC0,
.enable = s5p6440_sclk_ctrl,
},
.sources = &clkset_spi_mmc,
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 },
}, {
......@@ -527,7 +652,7 @@ static struct clksrc_clk clksrcs[] = {
.ctrlbit = S5P_CLKCON_SCLK0_MMC1,
.enable = s5p6440_sclk_ctrl,
},
.sources = &clkset_spi_mmc,
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 },
}, {
......@@ -537,7 +662,7 @@ static struct clksrc_clk clksrcs[] = {
.ctrlbit = S5P_CLKCON_SCLK0_MMC2,
.enable = s5p6440_sclk_ctrl,
},
.sources = &clkset_spi_mmc,
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 },
}, {
......@@ -557,7 +682,7 @@ static struct clksrc_clk clksrcs[] = {
.ctrlbit = S5P_CLKCON_SCLK0_SPI0,
.enable = s5p6440_sclk_ctrl,
},
.sources = &clkset_spi_mmc,
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
}, {
......@@ -567,17 +692,63 @@ static struct clksrc_clk clksrcs[] = {
.ctrlbit = S5P_CLKCON_SCLK0_SPI1,
.enable = s5p6440_sclk_ctrl,
},
.sources = &clkset_spi_mmc,
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
}
}, {
.clk = {
.name = "sclk_post",
.id = -1,
.ctrlbit = (1 << 10),
.enable = s5p6440_sclk_ctrl,
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 26, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
}, {
.clk = {
.name = "sclk_dispcon",
.id = -1,
.ctrlbit = (1 << 1),
.enable = s5p6440_sclk1_ctrl,
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_fimgvg",
.id = -1,
.ctrlbit = (1 << 2),
.enable = s5p6440_sclk1_ctrl,
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_audio2",
.id = -1,
.ctrlbit = (1 << 11),
.enable = s5p6440_sclk_ctrl,
},
.sources = &clkset_audio,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 3 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 24, .size = 4 },
},
};
/* Clock initialisation code */
static struct clksrc_clk *init_parents[] = {
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
&clk_mout_epll,
&clk_mout_mpll,
&clk_dout_mpll,
&clk_armclk,
&clk_hclk,
&clk_pclk,
&clk_hclk_low,
&clk_pclk_low,
};
void __init_or_cpufreq s5p6440_setup_clocks(void)
......@@ -593,21 +764,13 @@ void __init_or_cpufreq s5p6440_setup_clocks(void)
unsigned long apll;
unsigned long mpll;
unsigned int ptr;
u32 clkdiv0;
u32 clkdiv3;
/* Set S5P6440 functions for clk_fout_epll */
clk_fout_epll.enable = s5p6440_epll_enable;
clk_fout_epll.ops = &s5p6440_epll_ops;
/* Set S5P6440 functions for arm clock */
clk_arm.parent = &clk_mout_apll.clk;
clk_arm.ops = &s5p6440_clkarm_ops;
clk_48m.enable = s5p6440_clk48m_ctrl;
clkdiv0 = __raw_readl(S5P_CLK_DIV0);
clkdiv3 = __raw_readl(S5P_CLK_DIV3);
xtal_clk = clk_get(NULL, "ext_xtal");
BUG_ON(IS_ERR(xtal_clk));
......@@ -619,41 +782,28 @@ void __init_or_cpufreq s5p6440_setup_clocks(void)
mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502);
clk_fout_mpll.rate = mpll;
clk_fout_epll.rate = epll;
clk_fout_apll.rate = apll;
printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
" E=%ld.%ldMHz\n",
print_mhz(apll), print_mhz(mpll), print_mhz(epll));
fclk = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_ARM);
hclk = fclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK);
pclk = hclk / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK);
if (__raw_readl(S5P_OTHERS) & S5P_OTHERS_HCLK_LOW_SEL_MPLL) {
/* Asynchronous mode */
hclk_low = mpll / GET_DIV(clkdiv3, S5P_CLKDIV3_HCLK_LOW);
} else {
/* Synchronous mode */
hclk_low = apll / GET_DIV(clkdiv3, S5P_CLKDIV3_HCLK_LOW);
}
pclk_low = hclk_low / GET_DIV(clkdiv3, S5P_CLKDIV3_PCLK_LOW);
fclk = clk_get_rate(&clk_armclk.clk);
hclk = clk_get_rate(&clk_hclk.clk);
pclk = clk_get_rate(&clk_pclk.clk);
hclk_low = clk_get_rate(&clk_hclk_low.clk);
pclk_low = clk_get_rate(&clk_pclk_low.clk);
printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
" PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
print_mhz(hclk), print_mhz(hclk_low),
print_mhz(pclk), print_mhz(pclk_low));
clk_fout_mpll.rate = mpll;
clk_fout_epll.rate = epll;
clk_fout_apll.rate = apll;
clk_f.rate = fclk;
clk_h.rate = hclk;
clk_p.rate = pclk;
clk_h_low.rate = hclk_low;
clk_p_low.rate = pclk_low;
for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
s3c_set_clksrc(init_parents[ptr], true);
for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
s3c_set_clksrc(&clksrcs[ptr], true);
......@@ -661,13 +811,8 @@ void __init_or_cpufreq s5p6440_setup_clocks(void)
static struct clk *clks[] __initdata = {
&clk_ext,
&clk_mout_epll.clk,
&clk_mout_mpll.clk,
&clk_dout_mpll,
&clk_iis_cd_v40,
&clk_pcm_cd,
&clk_p_low,
&clk_h_low,
};
void __init s5p6440_register_clocks(void)
......@@ -680,6 +825,9 @@ void __init s5p6440_register_clocks(void)
if (ret > 0)
printk(KERN_ERR "Failed to register %u clocks\n", ret);
for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
s3c_register_clksrc(sysclks[ptr], 1);
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
......
......@@ -88,7 +88,7 @@ void __init s5p6440_init_irq(void)
s5p_init_irq(vic, ARRAY_SIZE(vic));
}
static struct sysdev_class s5p6440_sysclass = {
struct sysdev_class s5p6440_sysclass = {
.name = "s5p6440-core",
};
......
/* linux/arch/arm/mach-s5p6440/dev-audio.c
*
* 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 version 2 as
* published by the Free Software Foundation.
*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <plat/gpio-cfg.h>
#include <plat/audio.h>
#include <mach/gpio.h>
#include <mach/map.h>
#include <mach/dma.h>
#include <mach/irqs.h>
static int s5p6440_cfg_i2s(struct platform_device *pdev)
{
/* configure GPIO for i2s port */
switch (pdev->id) {
case -1:
s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5));
s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5));
s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5));
s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5));
s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5));
s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5));
s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5));
break;
default:
printk(KERN_ERR "Invalid Device %d\n", pdev->id);
return -EINVAL;
}
return 0;
}
static struct s3c_audio_pdata s3c_i2s_pdata = {
.cfg_gpio = s5p6440_cfg_i2s,
};
static struct resource s5p6440_iis0_resource[] = {
[0] = {
.start = S5P6440_PA_I2S,
.end = S5P6440_PA_I2S + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_I2S0_TX,
.end = DMACH_I2S0_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_I2S0_RX,
.end = DMACH_I2S0_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5p6440_device_iis = {
.name = "s3c64xx-iis-v4",
.id = -1,
.num_resources = ARRAY_SIZE(s5p6440_iis0_resource),
.resource = s5p6440_iis0_resource,
.dev = {
.platform_data = &s3c_i2s_pdata,
},
};
/* PCM Controller platform_devices */
static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev)
{
switch (pdev->id) {
case 0:
s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2));
break;
default:
printk(KERN_DEBUG "Invalid PCM Controller number!");
return -EINVAL;
}
return 0;
}
static struct s3c_audio_pdata s3c_pcm_pdata = {
.cfg_gpio = s5p6440_pcm_cfg_gpio,
};
static struct resource s5p6440_pcm0_resource[] = {
[0] = {
.start = S5P6440_PA_PCM,
.end = S5P6440_PA_PCM + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_PCM0_TX,
.end = DMACH_PCM0_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_PCM0_RX,
.end = DMACH_PCM0_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5p6440_device_pcm = {
.name = "samsung-pcm",
.id = 0,
.num_resources = ARRAY_SIZE(s5p6440_pcm0_resource),
.resource = s5p6440_pcm0_resource,
.dev = {
.platform_data = &s3c_pcm_pdata,
},
};
/*
* 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.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <plat/devs.h>
#include <plat/irqs.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include <plat/s3c-pl330-pdata.h>
static u64 dma_dmamask = DMA_BIT_MASK(32);
static struct resource s5p6440_pdma_resource[] = {
[0] = {
.start = S5P6440_PA_PDMA,
.end = S5P6440_PA_PDMA + SZ_4K,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_DMA0,
.end = IRQ_DMA0,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
.peri = {
[0] = DMACH_UART0_RX,
[1] = DMACH_UART0_TX,
[2] = DMACH_UART1_RX,
[3] = DMACH_UART1_TX,
[4] = DMACH_UART2_RX,
[5] = DMACH_UART2_TX,
[6] = DMACH_UART3_RX,
[7] = DMACH_UART3_TX,
[8] = DMACH_MAX,
[9] = DMACH_MAX,
[10] = DMACH_PCM0_TX,
[11] = DMACH_PCM0_RX,
[12] = DMACH_I2S0_TX,
[13] = DMACH_I2S0_RX,
[14] = DMACH_SPI0_TX,
[15] = DMACH_SPI0_RX,
[16] = DMACH_MAX,
[17] = DMACH_MAX,
[18] = DMACH_MAX,
[19] = DMACH_MAX,
[20] = DMACH_SPI1_TX,
[21] = DMACH_SPI1_RX,
[22] = DMACH_MAX,
[23] = DMACH_MAX,
[24] = DMACH_MAX,
[25] = DMACH_MAX,
[26] = DMACH_MAX,
[27] = DMACH_MAX,
[28] = DMACH_MAX,
[29] = DMACH_PWM,
[30] = DMACH_MAX,
[31] = DMACH_MAX,
},
};
static struct platform_device s5p6440_device_pdma = {
.name = "s3c-pl330",
.id = 1,
.num_resources = ARRAY_SIZE(s5p6440_pdma_resource),
.resource = s5p6440_pdma_resource,
.dev = {
.dma_mask = &dma_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s5p6440_pdma_pdata,
},
};
static struct platform_device *s5p6440_dmacs[] __initdata = {
&s5p6440_device_pdma,
};
static int __init s5p6440_dma_init(void)
{
platform_add_devices(s5p6440_dmacs, ARRAY_SIZE(s5p6440_dmacs));
return 0;
}
arch_initcall(s5p6440_dma_init);
/*
* 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.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MACH_DMA_H
#define __MACH_DMA_H
/* This platform uses the common S3C DMA API driver for PL330 */
#include <plat/s3c-dma-pl330.h>
#endif /* __MACH_DMA_H */
......@@ -29,6 +29,8 @@
#define S5P6440_PA_VIC0 (0xE4000000)
#define S5P_PA_VIC0 S5P6440_PA_VIC0
#define S5P6440_PA_PDMA 0xE9000000
#define S5P6440_PA_VIC1 (0xE4100000)
#define S5P_PA_VIC1 S5P6440_PA_VIC1
......@@ -61,6 +63,12 @@
#define S5P6440_PA_SDRAM (0x20000000)
#define S5P_PA_SDRAM S5P6440_PA_SDRAM
/* I2S */
#define S5P6440_PA_I2S 0xF2000000
/* PCM */
#define S5P6440_PA_PCM 0xF2100000
/* compatibiltiy defines. */
#define S3C_PA_UART S5P6440_PA_UART
#define S3C_PA_IIC S5P6440_PA_IIC0
......
/* linux/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
*
* Copyright (c) 2009 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/
*
* Copyright 2009 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
* Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
*
* S5P6440 - pwm clock and timer support
*
......@@ -14,16 +17,19 @@
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_PWMCLK_H
#define __ASM_ARCH_PWMCLK_H __FILE__
/**
* pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
* @cfg: The timer TCFG1 register bits shifted down to 0.
* @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)
{
return tcfg == S3C2410_TCFG1_MUX_TCLK;
return 0;
}
/**
......@@ -35,7 +41,7 @@ static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
*/
static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
{
return 1 << (1 + tcfg1);
return 1 << tcfg1;
}
/**
......@@ -45,7 +51,7 @@ static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
*/
static inline unsigned int pwm_tdiv_has_div1(void)
{
return 0;
return 1;
}
/**
......@@ -56,7 +62,9 @@ static inline unsigned int pwm_tdiv_has_div1(void)
*/
static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
{
return ilog2(div) - 1;
return ilog2(div);
}
#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
#define S3C_TCFG1_MUX_TCLK 0
#endif /* __ASM_ARCH_PWMCLK_H */
......@@ -84,6 +84,7 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
};
static struct platform_device *smdk6440_devices[] __initdata = {
&s5p6440_device_iis,
};
static void __init smdk6440_map_io(void)
......
/* linux/arch/arm/plat-s5p/setup-i2c0.c
/* linux/arch/arm/mach-s5p6440/setup-i2c0.c
*
* Copyright (c) 2009 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
......
......@@ -12,6 +12,7 @@ if ARCH_S5P6442
config CPU_S5P6442
bool
select PLAT_S5P
select S3C_PL330_DMA
help
Enable S5P6442 CPU support
......
......@@ -12,8 +12,12 @@ obj- :=
# Core support for S5P6442 system
obj-$(CONFIG_CPU_S5P6442) += cpu.o init.o clock.o
obj-$(CONFIG_CPU_S5P6442) += cpu.o init.o clock.o dma.o
obj-$(CONFIG_CPU_S5P6442) += setup-i2c0.o
# machine support
obj-$(CONFIG_MACH_SMDK6442) += mach-smdk6442.o
# device support
obj-y += dev-audio.o
......@@ -95,7 +95,7 @@ void __init s5p6442_init_irq(void)
s5p_init_irq(vic, ARRAY_SIZE(vic));
}
static struct sysdev_class s5p6442_sysclass = {
struct sysdev_class s5p6442_sysclass = {
.name = "s5p6442-core",
};
......
/* linux/arch/arm/mach-s5p6442/dev-audio.c
*
* 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 version 2 as
* published by the Free Software Foundation.
*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <plat/gpio-cfg.h>
#include <plat/audio.h>
#include <mach/gpio.h>
#include <mach/map.h>
#include <mach/dma.h>
#include <mach/irqs.h>
static int s5p6442_cfg_i2s(struct platform_device *pdev)
{
/* configure GPIO for i2s port */
switch (pdev->id) {
case 1:
s3c_gpio_cfgpin(S5P6442_GPC1(0), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6442_GPC1(1), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6442_GPC1(2), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6442_GPC1(3), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6442_GPC1(4), S3C_GPIO_SFN(2));
break;
case -1:
s3c_gpio_cfgpin(S5P6442_GPC0(0), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6442_GPC0(1), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6442_GPC0(2), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6442_GPC0(3), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5P6442_GPC0(4), S3C_GPIO_SFN(2));
break;
default:
printk(KERN_ERR "Invalid Device %d\n", pdev->id);
return -EINVAL;
}
return 0;
}
static struct s3c_audio_pdata s3c_i2s_pdata = {
.cfg_gpio = s5p6442_cfg_i2s,
};
static struct resource s5p6442_iis0_resource[] = {
[0] = {
.start = S5P6442_PA_I2S0,
.end = S5P6442_PA_I2S0 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_I2S0_TX,
.end = DMACH_I2S0_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_I2S0_RX,
.end = DMACH_I2S0_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5p6442_device_iis0 = {
.name = "s3c64xx-iis-v4",
.id = -1,
.num_resources = ARRAY_SIZE(s5p6442_iis0_resource),
.resource = s5p6442_iis0_resource,
.dev = {
.platform_data = &s3c_i2s_pdata,
},
};
static struct resource s5p6442_iis1_resource[] = {
[0] = {
.start = S5P6442_PA_I2S1,
.end = S5P6442_PA_I2S1 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_I2S1_TX,
.end = DMACH_I2S1_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_I2S1_RX,
.end = DMACH_I2S1_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5p6442_device_iis1 = {
.name = "s3c64xx-iis",
.id = 1,
.num_resources = ARRAY_SIZE(s5p6442_iis1_resource),
.resource = s5p6442_iis1_resource,
.dev = {
.platform_data = &s3c_i2s_pdata,
},
};
/* PCM Controller platform_devices */
static int s5p6442_pcm_cfg_gpio(struct platform_device *pdev)
{
switch (pdev->id) {
case 0:
s3c_gpio_cfgpin(S5P6442_GPC0(0), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5P6442_GPC0(1), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5P6442_GPC0(2), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5P6442_GPC0(3), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5P6442_GPC0(4), S3C_GPIO_SFN(3));
break;
case 1:
s3c_gpio_cfgpin(S5P6442_GPC1(0), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5P6442_GPC1(1), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5P6442_GPC1(2), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5P6442_GPC1(3), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5P6442_GPC1(4), S3C_GPIO_SFN(3));
break;
default:
printk(KERN_DEBUG "Invalid PCM Controller number!");
return -EINVAL;
}
return 0;
}
static struct s3c_audio_pdata s3c_pcm_pdata = {
.cfg_gpio = s5p6442_pcm_cfg_gpio,
};
static struct resource s5p6442_pcm0_resource[] = {
[0] = {
.start = S5P6442_PA_PCM0,
.end = S5P6442_PA_PCM0 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_PCM0_TX,
.end = DMACH_PCM0_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_PCM0_RX,
.end = DMACH_PCM0_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5p6442_device_pcm0 = {
.name = "samsung-pcm",
.id = 0,
.num_resources = ARRAY_SIZE(s5p6442_pcm0_resource),
.resource = s5p6442_pcm0_resource,
.dev = {
.platform_data = &s3c_pcm_pdata,
},
};
static struct resource s5p6442_pcm1_resource[] = {
[0] = {
.start = S5P6442_PA_PCM1,
.end = S5P6442_PA_PCM1 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_PCM1_TX,
.end = DMACH_PCM1_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_PCM1_RX,
.end = DMACH_PCM1_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5p6442_device_pcm1 = {
.name = "samsung-pcm",
.id = 1,
.num_resources = ARRAY_SIZE(s5p6442_pcm1_resource),
.resource = s5p6442_pcm1_resource,
.dev = {
.platform_data = &s3c_pcm_pdata,
},
};
/*
* 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.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <plat/devs.h>
#include <plat/irqs.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include <plat/s3c-pl330-pdata.h>
static u64 dma_dmamask = DMA_BIT_MASK(32);
static struct resource s5p6442_pdma_resource[] = {
[0] = {
.start = S5P6442_PA_PDMA,
.end = S5P6442_PA_PDMA + SZ_4K,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_PDMA,
.end = IRQ_PDMA,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c_pl330_platdata s5p6442_pdma_pdata = {
.peri = {
[0] = DMACH_UART0_RX,
[1] = DMACH_UART0_TX,
[2] = DMACH_UART1_RX,
[3] = DMACH_UART1_TX,
[4] = DMACH_UART2_RX,
[5] = DMACH_UART2_TX,
[6] = DMACH_MAX,
[7] = DMACH_MAX,
[8] = DMACH_MAX,
[9] = DMACH_I2S0_RX,
[10] = DMACH_I2S0_TX,
[11] = DMACH_I2S0S_TX,
[12] = DMACH_I2S1_RX,
[13] = DMACH_I2S1_TX,
[14] = DMACH_MAX,
[15] = DMACH_MAX,
[16] = DMACH_SPI0_RX,
[17] = DMACH_SPI0_TX,
[18] = DMACH_MAX,
[19] = DMACH_MAX,
[20] = DMACH_PCM0_RX,
[21] = DMACH_PCM0_TX,
[22] = DMACH_PCM1_RX,
[23] = DMACH_PCM1_TX,
[24] = DMACH_MAX,
[25] = DMACH_MAX,
[26] = DMACH_MAX,
[27] = DMACH_MSM_REQ0,
[28] = DMACH_MSM_REQ1,
[29] = DMACH_MSM_REQ2,
[30] = DMACH_MSM_REQ3,
[31] = DMACH_MAX,
},
};
static struct platform_device s5p6442_device_pdma = {
.name = "s3c-pl330",
.id = 1,
.num_resources = ARRAY_SIZE(s5p6442_pdma_resource),
.resource = s5p6442_pdma_resource,
.dev = {
.dma_mask = &dma_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s5p6442_pdma_pdata,
},
};
static struct platform_device *s5p6442_dmacs[] __initdata = {
&s5p6442_device_pdma,
};
static int __init s5p6442_dma_init(void)
{
platform_add_devices(s5p6442_dmacs, ARRAY_SIZE(s5p6442_dmacs));
return 0;
}
arch_initcall(s5p6442_dma_init);
/*
* 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.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MACH_DMA_H
#define __MACH_DMA_H
/* This platform uses the common S3C DMA API driver for PL330 */
#include <plat/s3c-dma-pl330.h>
#endif /* __MACH_DMA_H */
......@@ -34,6 +34,9 @@
#define S5P6442_PA_VIC2 (0xE4200000)
#define S5P_PA_VIC2 S5P6442_PA_VIC2
#define S5P6442_PA_MDMA 0xE8000000
#define S5P6442_PA_PDMA 0xE9000000
#define S5P6442_PA_TIMER (0xEA000000)
#define S5P_PA_TIMER S5P6442_PA_TIMER
......@@ -51,6 +54,14 @@
#define S5P6442_PA_SDRAM (0x20000000)
#define S5P_PA_SDRAM S5P6442_PA_SDRAM
/* I2S */
#define S5P6442_PA_I2S0 0xC0B00000
#define S5P6442_PA_I2S1 0xF2200000
/* PCM */
#define S5P6442_PA_PCM0 0xF2400000
#define S5P6442_PA_PCM1 0xF2500000
/* compatibiltiy defines. */
#define S3C_PA_UART S5P6442_PA_UART
#define S3C_PA_IIC S5P6442_PA_IIC0
......
/* linux/arch/arm/mach-s5p6442/include/mach/pwm-clock.h
*
* Copyright (c) 2010 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/
*
* Copyright 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* Based on arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
* Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
*
* S5P6442 - pwm clock and timer support
*
......@@ -21,14 +22,14 @@
/**
* pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
* @cfg: The timer TCFG1 register bits shifted down to 0.
* @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)
{
return tcfg == S3C2410_TCFG1_MUX_TCLK;
return tcfg == S3C64XX_TCFG1_MUX_TCLK;
}
/**
......@@ -40,7 +41,7 @@ static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
*/
static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
{
return 1 << (1 + tcfg1);
return 1 << tcfg1;
}
/**
......@@ -50,7 +51,7 @@ static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
*/
static inline unsigned int pwm_tdiv_has_div1(void)
{
return 0;
return 1;
}
/**
......@@ -61,9 +62,9 @@ static inline unsigned int pwm_tdiv_has_div1(void)
*/
static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
{
return ilog2(div) - 1;
return ilog2(div);
}
#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
#endif /* __ASM_ARCH_PWMCLK_H */
......@@ -65,6 +65,7 @@ static struct s3c2410_uartcfg smdk6442_uartcfgs[] __initdata = {
};
static struct platform_device *smdk6442_devices[] __initdata = {
&s5p6442_device_iis0,
};
static void __init smdk6442_map_io(void)
......
/* linux/arch/arm/mach-s5p6442/setup-i2c0.c
*
* Copyright (c) 2009 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* I2C0 GPIO configuration.
*
* Based on plat-s3c64xx/setup-i2c0.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/types.h>
struct platform_device; /* don't need the contents */
#include <plat/iic.h>
void s3c_i2c0_cfg_gpio(struct platform_device *dev)
{
/* Will be populated later */
}
......@@ -12,12 +12,22 @@ config CPU_S5PC100
help
Enable S5PC100 CPU support
config S5PC100_SETUP_FB_24BPP
bool
help
Common setup code for S5PC1XX with an 24bpp RGB display helper.
config S5PC100_SETUP_SDHCI
bool
select S5PC1XX_SETUP_SDHCI_GPIO
help
Internal helper functions for S5PC100 based SDHCI systems
config S5PC100_SETUP_I2C1
bool
help
Common setup code for i2c bus 1.
config MACH_SMDKC100
bool "SMDKC100"
select CPU_S5PC100
......@@ -26,9 +36,8 @@ config MACH_SMDKC100
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
select S5PC1XX_SETUP_I2C0
select S5PC1XX_SETUP_I2C1
select S5PC1XX_SETUP_FB_24BPP
select S5PC100_SETUP_FB_24BPP
select S5PC100_SETUP_I2C1
select S5PC100_SETUP_SDHCI
help
Machine support for the Samsung SMDKC100
......@@ -11,10 +11,13 @@ obj- :=
# Core support for S5PC100 system
obj-$(CONFIG_CPU_S5PC100) += cpu.o
obj-$(CONFIG_CPU_S5PC100) += cpu.o gpiolib.o
obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o
# Helper and device support
obj-$(CONFIG_S5PC100_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S5PC100_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S5PC100_SETUP_SDHCI) += setup-sdhci.o
# machine support
......
/* linux/arch/arm/mach-s5pc100/clock.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S5PC100 - 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/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <mach/map.h>
#include <plat/cpu-freq.h>
#include <mach/regs-clock.h>
#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/pll.h>
#include <plat/s5p-clock.h>
#include <plat/clock-clksrc.h>
#include <plat/s5pc100.h>
static struct clk s5p_clk_otgphy = {
.name = "otg_phy",
.id = -1,
};
static struct clk *clk_src_mout_href_list[] = {
[0] = &s5p_clk_27m,
[1] = &clk_fin_hpll,
};
static struct clksrc_sources clk_src_mout_href = {
.sources = clk_src_mout_href_list,
.nr_sources = ARRAY_SIZE(clk_src_mout_href_list),
};
static struct clksrc_clk clk_mout_href = {
.clk = {
.name = "mout_href",
.id = -1,
},
.sources = &clk_src_mout_href,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
};
static struct clk *clk_src_mout_48m_list[] = {
[0] = &clk_xusbxti,
[1] = &s5p_clk_otgphy,
};
static struct clksrc_sources clk_src_mout_48m = {
.sources = clk_src_mout_48m_list,
.nr_sources = ARRAY_SIZE(clk_src_mout_48m_list),
};
static struct clksrc_clk clk_mout_48m = {
.clk = {
.name = "mout_48m",
.id = -1,
},
.sources = &clk_src_mout_48m,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 1 },
};
static struct clksrc_clk clk_mout_mpll = {
.clk = {
.name = "mout_mpll",
.id = -1,
},
.sources = &clk_src_mpll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
};
static struct clksrc_clk clk_mout_apll = {
.clk = {
.name = "mout_apll",
.id = -1,
},
.sources = &clk_src_apll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
};
static struct clksrc_clk clk_mout_epll = {
.clk = {
.name = "mout_epll",
.id = -1,
},
.sources = &clk_src_epll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
};
static struct clk *clk_src_mout_hpll_list[] = {
[0] = &s5p_clk_27m,
};
static struct clksrc_sources clk_src_mout_hpll = {
.sources = clk_src_mout_hpll_list,
.nr_sources = ARRAY_SIZE(clk_src_mout_hpll_list),
};
static struct clksrc_clk clk_mout_hpll = {
.clk = {
.name = "mout_hpll",
.id = -1,
},
.sources = &clk_src_mout_hpll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
};
static struct clksrc_clk clk_div_apll = {
.clk = {
.name = "div_apll",
.id = -1,
.parent = &clk_mout_apll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 1 },
};
static struct clksrc_clk clk_div_arm = {
.clk = {
.name = "div_arm",
.id = -1,
.parent = &clk_div_apll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
};
static struct clksrc_clk clk_div_d0_bus = {
.clk = {
.name = "div_d0_bus",
.id = -1,
.parent = &clk_div_arm.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
};
static struct clksrc_clk clk_div_pclkd0 = {
.clk = {
.name = "div_pclkd0",
.id = -1,
.parent = &clk_div_d0_bus.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
};
static struct clksrc_clk clk_div_secss = {
.clk = {
.name = "div_secss",
.id = -1,
.parent = &clk_div_d0_bus.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 3 },
};
static struct clksrc_clk clk_div_apll2 = {
.clk = {
.name = "div_apll2",
.id = -1,
.parent = &clk_mout_apll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 3 },
};
static struct clk *clk_src_mout_am_list[] = {
[0] = &clk_mout_mpll.clk,
[1] = &clk_div_apll2.clk,
};
struct clksrc_sources clk_src_mout_am = {
.sources = clk_src_mout_am_list,
.nr_sources = ARRAY_SIZE(clk_src_mout_am_list),
};
static struct clksrc_clk clk_mout_am = {
.clk = {
.name = "mout_am",
.id = -1,
},
.sources = &clk_src_mout_am,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
};
static struct clksrc_clk clk_div_d1_bus = {
.clk = {
.name = "div_d1_bus",
.id = -1,
.parent = &clk_mout_am.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 3 },
};
static struct clksrc_clk clk_div_mpll2 = {
.clk = {
.name = "div_mpll2",
.id = -1,
.parent = &clk_mout_am.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 1 },
};
static struct clksrc_clk clk_div_mpll = {
.clk = {
.name = "div_mpll",
.id = -1,
.parent = &clk_mout_am.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 2 },
};
static struct clk *clk_src_mout_onenand_list[] = {
[0] = &clk_div_d0_bus.clk,
[1] = &clk_div_d1_bus.clk,
};
struct clksrc_sources clk_src_mout_onenand = {
.sources = clk_src_mout_onenand_list,
.nr_sources = ARRAY_SIZE(clk_src_mout_onenand_list),
};
static struct clksrc_clk clk_mout_onenand = {
.clk = {
.name = "mout_onenand",
.id = -1,
},
.sources = &clk_src_mout_onenand,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
};
static struct clksrc_clk clk_div_onenand = {
.clk = {
.name = "div_onenand",
.id = -1,
.parent = &clk_mout_onenand.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 2 },
};
static struct clksrc_clk clk_div_pclkd1 = {
.clk = {
.name = "div_pclkd1",
.id = -1,
.parent = &clk_div_d1_bus.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 3 },
};
static struct clksrc_clk clk_div_cam = {
.clk = {
.name = "div_cam",
.id = -1,
.parent = &clk_div_mpll2.clk,
},
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 24, .size = 5 },
};
static struct clksrc_clk clk_div_hdmi = {
.clk = {
.name = "div_hdmi",
.id = -1,
.parent = &clk_mout_hpll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 },
};
static int s5pc100_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;
}
static unsigned long s5pc100_epll_get_rate(struct clk *clk)
{
return clk->rate;
}
static u32 epll_div[][4] = {
{ 32750000, 131, 3, 4 },
{ 32768000, 131, 3, 4 },
{ 36000000, 72, 3, 3 },
{ 45000000, 90, 3, 3 },
{ 45158000, 90, 3, 3 },
{ 45158400, 90, 3, 3 },
{ 48000000, 96, 3, 3 },
{ 49125000, 131, 4, 3 },
{ 49152000, 131, 4, 3 },
{ 60000000, 120, 3, 3 },
{ 67737600, 226, 5, 3 },
{ 67738000, 226, 5, 3 },
{ 73800000, 246, 5, 3 },
{ 73728000, 246, 5, 3 },
{ 72000000, 144, 3, 3 },
{ 84000000, 168, 3, 3 },
{ 96000000, 96, 3, 2 },
{ 144000000, 144, 3, 2 },
{ 192000000, 96, 3, 1 }
};
static int s5pc100_epll_set_rate(struct clk *clk, unsigned long rate)
{
unsigned int epll_con;
unsigned int i;
if (clk->rate == rate) /* Return if nothing changed */
return 0;
epll_con = __raw_readl(S5P_EPLL_CON);
epll_con &= ~(PLL65XX_MDIV_MASK | PLL65XX_PDIV_MASK | PLL65XX_SDIV_MASK);
for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
if (epll_div[i][0] == rate) {
epll_con |= (epll_div[i][1] << PLL65XX_MDIV_SHIFT) |
(epll_div[i][2] << PLL65XX_PDIV_SHIFT) |
(epll_div[i][3] << PLL65XX_SDIV_SHIFT);
break;
}
}
if (i == ARRAY_SIZE(epll_div)) {
printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
return -EINVAL;
}
__raw_writel(epll_con, S5P_EPLL_CON);
clk->rate = rate;
return 0;
}
static struct clk_ops s5pc100_epll_ops = {
.get_rate = s5pc100_epll_get_rate,
.set_rate = s5pc100_epll_set_rate,
};
static int s5pc100_d0_0_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_D00, clk, enable);
}
static int s5pc100_d0_1_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_D01, clk, enable);
}
static int s5pc100_d0_2_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_D02, clk, enable);
}
static int s5pc100_d1_0_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_D10, clk, enable);
}
static int s5pc100_d1_1_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_D11, clk, enable);
}
static int s5pc100_d1_2_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_D12, clk, enable);
}
static int s5pc100_d1_3_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_D13, clk, enable);
}
static int s5pc100_d1_4_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_D14, clk, enable);
}
static int s5pc100_d1_5_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_D15, clk, enable);
}
static int s5pc100_sclk0_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_SCLK0, clk, enable);
}
static int s5pc100_sclk1_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_SCLK1, clk, enable);
}
/*
* The following clocks will be disabled during clock initialization. It is
* recommended to keep the following clocks disabled until the driver requests
* for enabling the clock.
*/
static struct clk init_clocks_disable[] = {
{
.name = "cssys",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "secss",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "g2d",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "mdma",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "cfcon",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "nfcon",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "onenandc",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "sdm",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_2_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "seckey",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_2_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "hsmmc",
.id = 2,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "hsmmc",
.id = 1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "hsmmc",
.id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "modemif",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "otg",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "usbhost",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "pdma",
.id = 1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "pdma",
.id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "lcd",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "rotator",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "fimc",
.id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "fimc",
.id = 1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "fimc",
.id = 2,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "jpeg",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "mipi-dsim",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "mipi-csis",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_1_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "g3d",
.id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "tv",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_2_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "vp",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_2_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "mixer",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_2_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "hdmi",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_2_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "mfc",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_2_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "apc",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "iec",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "systimer",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "watchdog",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "rtc",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = "i2c",
.id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "i2c",
.id = 1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "spi",
.id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "spi",
.id = 1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "spi",
.id = 2,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "irda",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = "ccan",
.id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 10),
}, {
.name = "ccan",
.id = 1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 11),
}, {
.name = "hsitx",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 12),
}, {
.name = "hsirx",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 13),
}, {
.name = "iis",
.id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "iis",
.id = 1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "iis",
.id = 2,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "ac97",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "pcm",
.id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "pcm",
.id = 1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "spdif",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "adc",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "keyif",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "spi_48m",
.id = 0,
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "spi_48m",
.id = 1,
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "spi_48m",
.id = 2,
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = "mmc_48m",
.id = 0,
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 15),
}, {
.name = "mmc_48m",
.id = 1,
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 16),
}, {
.name = "mmc_48m",
.id = 2,
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 17),
},
};
static struct clk clk_vclk54m = {
.name = "vclk_54m",
.id = -1,
.rate = 54000000,
};
static struct clk clk_i2scdclk0 = {
.name = "i2s_cdclk0",
.id = -1,
};
static struct clk clk_i2scdclk1 = {
.name = "i2s_cdclk1",
.id = -1,
};
static struct clk clk_i2scdclk2 = {
.name = "i2s_cdclk2",
.id = -1,
};
static struct clk clk_pcmcdclk0 = {
.name = "pcm_cdclk0",
.id = -1,
};
static struct clk clk_pcmcdclk1 = {
.name = "pcm_cdclk1",
.id = -1,
};
static struct clk *clk_src_group1_list[] = {
[0] = &clk_mout_epll.clk,
[1] = &clk_div_mpll2.clk,
[2] = &clk_fin_epll,
[3] = &clk_mout_hpll.clk,
};
struct clksrc_sources clk_src_group1 = {
.sources = clk_src_group1_list,
.nr_sources = ARRAY_SIZE(clk_src_group1_list),
};
static struct clk *clk_src_group2_list[] = {
[0] = &clk_mout_epll.clk,
[1] = &clk_div_mpll.clk,
};
struct clksrc_sources clk_src_group2 = {
.sources = clk_src_group2_list,
.nr_sources = ARRAY_SIZE(clk_src_group2_list),
};
static struct clk *clk_src_group3_list[] = {
[0] = &clk_mout_epll.clk,
[1] = &clk_div_mpll.clk,
[2] = &clk_fin_epll,
[3] = &clk_i2scdclk0,
[4] = &clk_pcmcdclk0,
[5] = &clk_mout_hpll.clk,
};
struct clksrc_sources clk_src_group3 = {
.sources = clk_src_group3_list,
.nr_sources = ARRAY_SIZE(clk_src_group3_list),
};
static struct clk *clk_src_group4_list[] = {
[0] = &clk_mout_epll.clk,
[1] = &clk_div_mpll.clk,
[2] = &clk_fin_epll,
[3] = &clk_i2scdclk1,
[4] = &clk_pcmcdclk1,
[5] = &clk_mout_hpll.clk,
};
struct clksrc_sources clk_src_group4 = {
.sources = clk_src_group4_list,
.nr_sources = ARRAY_SIZE(clk_src_group4_list),
};
static struct clk *clk_src_group5_list[] = {
[0] = &clk_mout_epll.clk,
[1] = &clk_div_mpll.clk,
[2] = &clk_fin_epll,
[3] = &clk_i2scdclk2,
[4] = &clk_mout_hpll.clk,
};
struct clksrc_sources clk_src_group5 = {
.sources = clk_src_group5_list,
.nr_sources = ARRAY_SIZE(clk_src_group5_list),
};
static struct clk *clk_src_group6_list[] = {
[0] = &s5p_clk_27m,
[1] = &clk_vclk54m,
[2] = &clk_div_hdmi.clk,
};
struct clksrc_sources clk_src_group6 = {
.sources = clk_src_group6_list,
.nr_sources = ARRAY_SIZE(clk_src_group6_list),
};
static struct clk *clk_src_group7_list[] = {
[0] = &clk_mout_epll.clk,
[1] = &clk_div_mpll.clk,
[2] = &clk_mout_hpll.clk,
[3] = &clk_vclk54m,
};
struct clksrc_sources clk_src_group7 = {
.sources = clk_src_group7_list,
.nr_sources = ARRAY_SIZE(clk_src_group7_list),
};
static struct clk *clk_src_mmc0_list[] = {
[0] = &clk_mout_epll.clk,
[1] = &clk_div_mpll.clk,
[2] = &clk_fin_epll,
};
struct clksrc_sources clk_src_mmc0 = {
.sources = clk_src_mmc0_list,
.nr_sources = ARRAY_SIZE(clk_src_mmc0_list),
};
static struct clk *clk_src_mmc12_list[] = {
[0] = &clk_mout_epll.clk,
[1] = &clk_div_mpll.clk,
[2] = &clk_fin_epll,
[3] = &clk_mout_hpll.clk,
};
struct clksrc_sources clk_src_mmc12 = {
.sources = clk_src_mmc12_list,
.nr_sources = ARRAY_SIZE(clk_src_mmc12_list),
};
static struct clk *clk_src_irda_usb_list[] = {
[0] = &clk_mout_epll.clk,
[1] = &clk_div_mpll.clk,
[2] = &clk_fin_epll,
[3] = &clk_mout_hpll.clk,
};
struct clksrc_sources clk_src_irda_usb = {
.sources = clk_src_irda_usb_list,
.nr_sources = ARRAY_SIZE(clk_src_irda_usb_list),
};
static struct clk *clk_src_pwi_list[] = {
[0] = &clk_fin_epll,
[1] = &clk_mout_epll.clk,
[2] = &clk_div_mpll.clk,
};
struct clksrc_sources clk_src_pwi = {
.sources = clk_src_pwi_list,
.nr_sources = ARRAY_SIZE(clk_src_pwi_list),
};
static struct clksrc_clk clksrcs[] = {
{
.clk = {
.name = "sclk_spi",
.id = 0,
.ctrlbit = (1 << 4),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_spi",
.id = 1,
.ctrlbit = (1 << 5),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
}, {
.clk = {
.name = "sclk_spi",
.id = 2,
.ctrlbit = (1 << 6),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 12, .size = 4 },
}, {
.clk = {
.name = "uclk1",
.id = -1,
.ctrlbit = (1 << 3),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group2,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_mixer",
.id = -1,
.ctrlbit = (1 << 6),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group6,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 },
}, {
.clk = {
.name = "sclk_audio",
.id = 0,
.ctrlbit = (1 << 8),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_group3,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
}, {
.clk = {
.name = "sclk_audio",
.id = 1,
.ctrlbit = (1 << 9),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_group4,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
}, {
.clk = {
.name = "sclk_audio",
.id = 2,
.ctrlbit = (1 << 10),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_group5,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
}, {
.clk = {
.name = "sclk_lcd",
.id = -1,
.ctrlbit = (1 << 0),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_group7,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 12, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
}, {
.clk = {
.name = "sclk_fimc",
.id = 0,
.ctrlbit = (1 << 1),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_group7,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 16, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 },
}, {
.clk = {
.name = "sclk_fimc",
.id = 1,
.ctrlbit = (1 << 2),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_group7,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 20, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 },
}, {
.clk = {
.name = "sclk_fimc",
.id = 2,
.ctrlbit = (1 << 3),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_group7,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 24, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 24, .size = 4 },
}, {
.clk = {
.name = "mmc_bus",
.id = 0,
.ctrlbit = (1 << 12),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_mmc0,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "mmc_bus",
.id = 1,
.ctrlbit = (1 << 13),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_mmc12,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "mmc_bus",
.id = 2,
.ctrlbit = (1 << 14),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_mmc12,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
}, {
.clk = {
.name = "sclk_irda",
.id = 2,
.ctrlbit = (1 << 10),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_irda_usb,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
}, {
.clk = {
.name = "sclk_irda",
.id = -1,
.ctrlbit = (1 << 10),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_mmc12,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 },
}, {
.clk = {
.name = "sclk_pwi",
.id = -1,
.ctrlbit = (1 << 1),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_pwi,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 0, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 3 },
}, {
.clk = {
.name = "sclk_uhost",
.id = -1,
.ctrlbit = (1 << 11),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_irda_usb,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 20, .size = 4 },
},
};
/* Clock initialisation code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
&clk_mout_epll,
&clk_mout_mpll,
&clk_mout_hpll,
&clk_mout_href,
&clk_mout_48m,
&clk_div_apll,
&clk_div_arm,
&clk_div_d0_bus,
&clk_div_pclkd0,
&clk_div_secss,
&clk_div_apll2,
&clk_mout_am,
&clk_div_d1_bus,
&clk_div_mpll2,
&clk_div_mpll,
&clk_mout_onenand,
&clk_div_onenand,
&clk_div_pclkd1,
&clk_div_cam,
&clk_div_hdmi,
};
void __init_or_cpufreq s5pc100_setup_clocks(void)
{
unsigned long xtal;
unsigned long arm;
unsigned long hclkd0;
unsigned long hclkd1;
unsigned long pclkd0;
unsigned long pclkd1;
unsigned long apll;
unsigned long mpll;
unsigned long epll;
unsigned long hpll;
unsigned int ptr;
/* Set S5PC100 functions for clk_fout_epll */
clk_fout_epll.enable = s5pc100_epll_enable;
clk_fout_epll.ops = &s5pc100_epll_ops;
printk(KERN_DEBUG "%s: registering clocks\n", __func__);
xtal = clk_get_rate(&clk_xtal);
printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
apll = s5p_get_pll65xx(xtal, __raw_readl(S5P_APLL_CON));
mpll = s5p_get_pll65xx(xtal, __raw_readl(S5P_MPLL_CON));
epll = s5p_get_pll65xx(xtal, __raw_readl(S5P_EPLL_CON));
hpll = s5p_get_pll65xx(xtal, __raw_readl(S5P_HPLL_CON));
printk(KERN_INFO "S5PC100: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz, E=%ld.%ldMHz, H=%ld.%ldMHz\n",
print_mhz(apll), print_mhz(mpll), print_mhz(epll), print_mhz(hpll));
clk_fout_apll.rate = apll;
clk_fout_mpll.rate = mpll;
clk_fout_epll.rate = epll;
clk_mout_hpll.clk.rate = hpll;
for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
s3c_set_clksrc(&clksrcs[ptr], true);
arm = clk_get_rate(&clk_div_arm.clk);
hclkd0 = clk_get_rate(&clk_div_d0_bus.clk);
pclkd0 = clk_get_rate(&clk_div_pclkd0.clk);
hclkd1 = clk_get_rate(&clk_div_d1_bus.clk);
pclkd1 = clk_get_rate(&clk_div_pclkd1.clk);
printk(KERN_INFO "S5PC100: HCLKD0=%ld.%ldMHz, HCLKD1=%ld.%ldMHz, PCLKD0=%ld.%ldMHz, PCLKD1=%ld.%ldMHz\n",
print_mhz(hclkd0), print_mhz(hclkd1), print_mhz(pclkd0), print_mhz(pclkd1));
clk_f.rate = arm;
clk_h.rate = hclkd1;
clk_p.rate = pclkd1;
}
/*
* The following clocks will be enabled during clock initialization.
*/
static struct clk init_clocks[] = {
{
.name = "tzic",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "intc",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_0_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "ebi",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "intmem",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "sromc",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "dmc",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "chipid",
.id = -1,
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_1_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "gpio",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "uart",
.id = 0,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 0),
}, {
.name = "uart",
.id = 1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "uart",
.id = 2,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = "uart",
.id = 3,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_4_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "timers",
.id = -1,
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_3_ctrl,
.ctrlbit = (1 << 6),
},
};
static struct clk *clks[] __initdata = {
&clk_ext,
&clk_i2scdclk0,
&clk_i2scdclk1,
&clk_i2scdclk2,
&clk_pcmcdclk0,
&clk_pcmcdclk1,
};
void __init s5pc100_register_clocks(void)
{
struct clk *clkp;
int ret;
int ptr;
s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
s3c_register_clksrc(sysclks[ptr], 1);
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
clkp = init_clocks_disable;
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
(clkp->enable)(clkp, 0);
}
s3c_pwmclk_init();
}
......@@ -17,11 +17,11 @@
#include <linux/gpio.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
#include <plat/regs-gpio.h>
/* S5PC100 GPIO bank summary:
*
......@@ -61,74 +61,7 @@
* L3 8 4Bit None
*/
#define OFF_GPCON (0x00)
#define OFF_GPDAT (0x04)
#define con_4bit_shift(__off) ((__off) * 4)
#if 1
#define gpio_dbg(x...) do { } while (0)
#else
#define gpio_dbg(x...) printk(KERN_DEBUG x)
#endif
/* The s5pc1xx_gpiolib routines are to control the gpio banks where
* the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
* following example:
*
* base + 0x00: Control register, 4 bits per gpio
* gpio n: 4 bits starting at (4*n)
* 0000 = input, 0001 = output, others mean special-function
* base + 0x04: Data register, 1 bit per gpio
* bit n: data bit n
*
* Note, since the data register is one bit per gpio and is at base + 0x4
* we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
* the output.
*/
static int s5pc1xx_gpiolib_input(struct gpio_chip *chip, unsigned offset)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
void __iomem *base = ourchip->base;
unsigned long con;
con = __raw_readl(base + OFF_GPCON);
con &= ~(0xf << con_4bit_shift(offset));
__raw_writel(con, base + OFF_GPCON);
gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
return 0;
}
static int s5pc1xx_gpiolib_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
void __iomem *base = ourchip->base;
unsigned long con;
unsigned long dat;
con = __raw_readl(base + OFF_GPCON);
con &= ~(0xf << con_4bit_shift(offset));
con |= 0x1 << con_4bit_shift(offset);
dat = __raw_readl(base + OFF_GPDAT);
if (value)
dat |= 1 << offset;
else
dat &= ~(1 << offset);
__raw_writel(dat, base + OFF_GPDAT);
__raw_writel(con, base + OFF_GPCON);
__raw_writel(dat, base + OFF_GPDAT);
gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
return 0;
}
#if 0
static int s5pc1xx_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
{
return S3C_IRQ_GPIO(chip->base + offset);
......@@ -152,7 +85,7 @@ static int s5pc1xx_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset)
return IRQ_EINT(24 + offset);
return -EINVAL;
}
#endif
static struct s3c_gpio_cfg gpio_cfg = {
.set_config = s3c_gpio_setcfg_s3c64xx_4bit,
.set_pull = s3c_gpio_setpull_updown,
......@@ -452,12 +385,9 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
extern struct irq_chip s5pc1xx_gpioint;
extern void s5pc1xx_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc);
static __init void s5pc1xx_gpiolib_link(struct s3c_gpio_chip *chip)
static __init void s5pc100_gpiolib_link(struct s3c_gpio_chip *chip)
{
chip->chip.direction_input = s5pc1xx_gpiolib_input;
chip->chip.direction_output = s5pc1xx_gpiolib_output;
chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
#if 0
/* Interrupt */
if (chip->config == &gpio_cfg) {
int i, irq;
......@@ -473,31 +403,26 @@ static __init void s5pc1xx_gpiolib_link(struct s3c_gpio_chip *chip)
}
} else if (chip->config == &gpio_cfg_eint)
chip->chip.to_irq = s5pc1xx_gpiolib_to_eint;
}
static __init void s5pc1xx_gpiolib_add(struct s3c_gpio_chip *chips,
int nr_chips,
void (*fn)(struct s3c_gpio_chip *))
{
for (; nr_chips > 0; nr_chips--, chips++) {
if (fn)
(fn)(chips);
s3c_gpiolib_add(chips);
}
#endif
}
static __init int s5pc1xx_gpiolib_init(void)
{
struct s3c_gpio_chip *chips;
struct s3c_gpio_chip *chip;
int nr_chips;
chips = s5pc100_gpio_chips;
nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
chip = s5pc100_gpio_chips;
nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
for (; nr_chips > 0; nr_chips--, chip++)
s5pc100_gpiolib_link(chip);
s5pc1xx_gpiolib_add(chips, nr_chips, s5pc1xx_gpiolib_link);
samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips,
ARRAY_SIZE(s5pc100_gpio_chips));
#if 0
/* Interrupt */
set_irq_chained_handler(IRQ_GPIOINT, s5pc1xx_irq_gpioint_handler);
#endif
return 0;
}
core_initcall(s5pc1xx_gpiolib_init);
......@@ -12,6 +12,9 @@
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_GPIO_H
#define __ASM_ARCH_GPIO_H __FILE__
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
......@@ -52,11 +55,6 @@
#define S5PC100_GPIO_L2_NR (8)
#define S5PC100_GPIO_L3_NR (8)
#define S5PC100_GPIO_L4_NR (8)
#define S5PC100_GPIO_MP00_NR (8)
#define S5PC100_GPIO_MP01_NR (8)
#define S5PC100_GPIO_MP02_NR (8)
#define S5PC100_GPIO_MP03_NR (8)
#define S5PC100_GPIO_MP04_NR (5)
/* GPIO bank numbes */
......@@ -65,50 +63,45 @@
* change from one gpio bank to another can be caught.
*/
#define S5PC1XX_GPIO_NEXT(__gpio) \
#define S5PC100_GPIO_NEXT(__gpio) \
((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
enum s3c_gpio_number {
enum s5p_gpio_number {
S5PC100_GPIO_A0_START = 0,
S5PC100_GPIO_A1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_A0),
S5PC100_GPIO_B_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_A1),
S5PC100_GPIO_C_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_B),
S5PC100_GPIO_D_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_C),
S5PC100_GPIO_E0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_D),
S5PC100_GPIO_E1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_E0),
S5PC100_GPIO_F0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_E1),
S5PC100_GPIO_F1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_F0),
S5PC100_GPIO_F2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_F1),
S5PC100_GPIO_F3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_F2),
S5PC100_GPIO_G0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_F3),
S5PC100_GPIO_G1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_G0),
S5PC100_GPIO_G2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_G1),
S5PC100_GPIO_G3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_G2),
S5PC100_GPIO_H0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_G3),
S5PC100_GPIO_H1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_H0),
S5PC100_GPIO_H2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_H1),
S5PC100_GPIO_H3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_H2),
S5PC100_GPIO_I_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_H3),
S5PC100_GPIO_J0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_I),
S5PC100_GPIO_J1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_J0),
S5PC100_GPIO_J2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_J1),
S5PC100_GPIO_J3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_J2),
S5PC100_GPIO_J4_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_J3),
S5PC100_GPIO_K0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_J4),
S5PC100_GPIO_K1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_K0),
S5PC100_GPIO_K2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_K1),
S5PC100_GPIO_K3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_K2),
S5PC100_GPIO_L0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_K3),
S5PC100_GPIO_L1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_L0),
S5PC100_GPIO_L2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_L1),
S5PC100_GPIO_L3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_L2),
S5PC100_GPIO_L4_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_L3),
S5PC100_GPIO_MP00_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_L4),
S5PC100_GPIO_MP01_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_MP00),
S5PC100_GPIO_MP02_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_MP01),
S5PC100_GPIO_MP03_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_MP02),
S5PC100_GPIO_MP04_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_MP03),
S5PC100_GPIO_END = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_MP04),
S5PC100_GPIO_A1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_A0),
S5PC100_GPIO_B_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_A1),
S5PC100_GPIO_C_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_B),
S5PC100_GPIO_D_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_C),
S5PC100_GPIO_E0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_D),
S5PC100_GPIO_E1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_E0),
S5PC100_GPIO_F0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_E1),
S5PC100_GPIO_F1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F0),
S5PC100_GPIO_F2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F1),
S5PC100_GPIO_F3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F2),
S5PC100_GPIO_G0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F3),
S5PC100_GPIO_G1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G0),
S5PC100_GPIO_G2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G1),
S5PC100_GPIO_G3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G2),
S5PC100_GPIO_H0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G3),
S5PC100_GPIO_H1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H0),
S5PC100_GPIO_H2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H1),
S5PC100_GPIO_H3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H2),
S5PC100_GPIO_I_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H3),
S5PC100_GPIO_J0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_I),
S5PC100_GPIO_J1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J0),
S5PC100_GPIO_J2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J1),
S5PC100_GPIO_J3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J2),
S5PC100_GPIO_J4_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J3),
S5PC100_GPIO_K0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J4),
S5PC100_GPIO_K1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K0),
S5PC100_GPIO_K2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K1),
S5PC100_GPIO_K3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K2),
S5PC100_GPIO_L0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K3),
S5PC100_GPIO_L1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L0),
S5PC100_GPIO_L2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L1),
S5PC100_GPIO_L3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L2),
S5PC100_GPIO_L4_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L3),
S5PC100_GPIO_END = S5PC100_GPIO_NEXT(S5PC100_GPIO_L4),
};
/* S5PC100 GPIO number definitions. */
......@@ -146,17 +139,13 @@ enum s3c_gpio_number {
#define S5PC100_GPL2(_nr) (S5PC100_GPIO_L2_START + (_nr))
#define S5PC100_GPL3(_nr) (S5PC100_GPIO_L3_START + (_nr))
#define S5PC100_GPL4(_nr) (S5PC100_GPIO_L4_START + (_nr))
#define S5PC100_MP00(_nr) (S5PC100_GPIO_MP00_START + (_nr))
#define S5PC100_MP01(_nr) (S5PC100_GPIO_MP01_START + (_nr))
#define S5PC100_MP02(_nr) (S5PC100_GPIO_MP02_START + (_nr))
#define S5PC100_MP03(_nr) (S5PC100_GPIO_MP03_START + (_nr))
#define S5PC100_MP04(_nr) (S5PC100_GPIO_MP04_START + (_nr))
#define S5PC100_MP05(_nr) (S5PC100_GPIO_MP05_START + (_nr))
/* It used the end of the S5PC1XX gpios */
/* It used the end of the S5PC100 gpios */
#define S3C_GPIO_END S5PC100_GPIO_END
/* define the number of gpios we need to the one after the MP04() range */
#define ARCH_NR_GPIOS (S5PC100_GPIO_END + 1)
#include <asm-generic/gpio.h>
#endif /* __ASM_ARCH_GPIO_H */
/* linux/arch/arm/mach-s5pc100/include/mach/regs-clock.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S5PC100 - Clock 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_ARCH_REGS_CLOCK_H
#define __ASM_ARCH_REGS_CLOCK_H __FILE__
#include <mach/map.h>
#define S5P_CLKREG(x) (S3C_VA_SYS + (x))
#define S5P_APLL_LOCK S5P_CLKREG(0x00)
#define S5P_MPLL_LOCK S5P_CLKREG(0x04)
#define S5P_EPLL_LOCK S5P_CLKREG(0x08)
#define S5P_HPLL_LOCK S5P_CLKREG(0x0C)
#define S5P_APLL_CON S5P_CLKREG(0x100)
#define S5P_MPLL_CON S5P_CLKREG(0x104)
#define S5P_EPLL_CON S5P_CLKREG(0x108)
#define S5P_HPLL_CON S5P_CLKREG(0x10C)
#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
#define S5P_CLK_SRC1 S5P_CLKREG(0x204)
#define S5P_CLK_SRC2 S5P_CLKREG(0x208)
#define S5P_CLK_SRC3 S5P_CLKREG(0x20C)
#define S5P_CLK_DIV0 S5P_CLKREG(0x300)
#define S5P_CLK_DIV1 S5P_CLKREG(0x304)
#define S5P_CLK_DIV2 S5P_CLKREG(0x308)
#define S5P_CLK_DIV3 S5P_CLKREG(0x30C)
#define S5P_CLK_DIV4 S5P_CLKREG(0x310)
#define S5P_CLK_OUT S5P_CLKREG(0x400)
#define S5P_CLKGATE_D00 S5P_CLKREG(0x500)
#define S5P_CLKGATE_D01 S5P_CLKREG(0x504)
#define S5P_CLKGATE_D02 S5P_CLKREG(0x508)
#define S5P_CLKGATE_D10 S5P_CLKREG(0x520)
#define S5P_CLKGATE_D11 S5P_CLKREG(0x524)
#define S5P_CLKGATE_D12 S5P_CLKREG(0x528)
#define S5P_CLKGATE_D13 S5P_CLKREG(0x52C)
#define S5P_CLKGATE_D14 S5P_CLKREG(0x530)
#define S5P_CLKGATE_D15 S5P_CLKREG(0x534)
#define S5P_CLKGATE_D20 S5P_CLKREG(0x540)
#define S5P_CLKGATE_SCLK0 S5P_CLKREG(0x560)
#define S5P_CLKGATE_SCLK1 S5P_CLKREG(0x564)
/* CLKDIV0 */
#define S5P_CLKDIV0_D0_MASK (0x7<<8)
#define S5P_CLKDIV0_D0_SHIFT (8)
#define S5P_CLKDIV0_PCLKD0_MASK (0x7<<12)
#define S5P_CLKDIV0_PCLKD0_SHIFT (12)
/* CLKDIV1 */
#define S5P_CLKDIV1_D1_MASK (0x7<<12)
#define S5P_CLKDIV1_D1_SHIFT (12)
#define S5P_CLKDIV1_PCLKD1_MASK (0x7<<16)
#define S5P_CLKDIV1_PCLKD1_SHIFT (16)
#endif /* __ASM_ARCH_REGS_CLOCK_H */
......@@ -3,11 +3,11 @@
* Copyright 2009 Samsung Electronics Co.
* Byungho Min <bhmin@samsung.com>
*
* S5PC1XX - GPIO register definitions
* S5PC100 - GPIO register definitions
*/
#ifndef __ASM_PLAT_S5PC1XX_REGS_GPIO_H
#define __ASM_PLAT_S5PC1XX_REGS_GPIO_H __FILE__
#ifndef __ASM_MACH_S5PC100_REGS_GPIO_H
#define __ASM_MACH_S5PC100_REGS_GPIO_H __FILE__
#include <mach/map.h>
......@@ -66,5 +66,5 @@
#define S5PC100_GPx_OUTPUT(__gpio) (0x1 << ((__gpio) * 4))
#define S5PC100_GPx_CONMASK(__gpio) (0xf << ((__gpio) * 4))
#endif /* __ASM_PLAT_S5PC1XX_REGS_GPIO_H */
#endif /* __ASM_MACH_S5PC100_REGS_GPIO_H */
......@@ -35,7 +35,6 @@
#include <plat/regs-serial.h>
#include <plat/gpio-cfg.h>
#include <plat/regs-gpio.h>
#include <plat/clock.h>
#include <plat/devs.h>
......
/*
* linux/arch/arm/plat-s5pc100/setup-fb-24bpp.c
* linux/arch/arm/mach-s5pc100/setup-fb-24bpp.c
*
* Copyright 2009 Samsung Electronics
*
* Base S5PC1XX setup information for 24bpp LCD framebuffer
* Base S5PC100 setup information for 24bpp LCD framebuffer
*
* 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
......@@ -19,7 +19,6 @@
#include <mach/map.h>
#include <plat/fb.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-s5pc1xx.h>
#define DISR_OFFSET 0x7008
......
/* linux/arch/arm/plat-s5pc1xx/setup-i2c0.c
/* linux/arch/arm/mach-s5pc100/setup-i2c0.c
*
* Copyright 2009 Samsung Electronics Co.
* Byungho Min <bhmin@samsung.com>
*
* Base S5PC1XX I2C bus 0 gpio configuration
* Base S5PC100 I2C bus 0 gpio configuration
*
* Based on plat-s3c64xx/setup-i2c0.c
*
......
/* linux/arch/arm/plat-s3c64xx/setup-i2c1.c
/* linux/arch/arm/mach-s5pc100/setup-i2c1.c
*
* Copyright 2009 Samsung Electronics Co.
* Byungho Min <bhmin@samsung.com>
*
* Base S5PC1XX I2C bus 1 gpio configuration
* Base S5PC100 I2C bus 1 gpio configuration
*
* Based on plat-s3c64xx/setup-i2c1.c
*
......
......@@ -12,6 +12,7 @@ if ARCH_S5PV210
config CPU_S5PV210
bool
select PLAT_S5P
select S3C_PL330_DMA
help
Enable S5PV210 CPU support
......
......@@ -12,9 +12,14 @@ obj- :=
# Core support for S5PV210 system
obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o
obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o gpiolib.o
obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o
# machine support
obj-$(CONFIG_MACH_SMDKV210) += mach-smdkv210.o
obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o
# device support
obj-y += dev-audio.o
......@@ -31,6 +31,128 @@
#include <plat/clock-clksrc.h>
#include <plat/s5pv210.h>
static struct clksrc_clk clk_mout_apll = {
.clk = {
.name = "mout_apll",
.id = -1,
},
.sources = &clk_src_apll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
};
static struct clksrc_clk clk_mout_epll = {
.clk = {
.name = "mout_epll",
.id = -1,
},
.sources = &clk_src_epll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
};
static struct clksrc_clk clk_mout_mpll = {
.clk = {
.name = "mout_mpll",
.id = -1,
},
.sources = &clk_src_mpll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
};
static struct clk *clkset_armclk_list[] = {
[0] = &clk_mout_apll.clk,
[1] = &clk_mout_mpll.clk,
};
static struct clksrc_sources clkset_armclk = {
.sources = clkset_armclk_list,
.nr_sources = ARRAY_SIZE(clkset_armclk_list),
};
static struct clksrc_clk clk_armclk = {
.clk = {
.name = "armclk",
.id = -1,
},
.sources = &clkset_armclk,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 3 },
};
static struct clksrc_clk clk_hclk_msys = {
.clk = {
.name = "hclk_msys",
.id = -1,
.parent = &clk_armclk.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
};
static struct clksrc_clk clk_pclk_msys = {
.clk = {
.name = "pclk_msys",
.id = -1,
.parent = &clk_hclk_msys.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
};
static struct clksrc_clk clk_sclk_a2m = {
.clk = {
.name = "sclk_a2m",
.id = -1,
.parent = &clk_mout_apll.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
};
static struct clk *clkset_hclk_sys_list[] = {
[0] = &clk_mout_mpll.clk,
[1] = &clk_sclk_a2m.clk,
};
static struct clksrc_sources clkset_hclk_sys = {
.sources = clkset_hclk_sys_list,
.nr_sources = ARRAY_SIZE(clkset_hclk_sys_list),
};
static struct clksrc_clk clk_hclk_dsys = {
.clk = {
.name = "hclk_dsys",
.id = -1,
},
.sources = &clkset_hclk_sys,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 },
};
static struct clksrc_clk clk_pclk_dsys = {
.clk = {
.name = "pclk_dsys",
.id = -1,
.parent = &clk_hclk_dsys.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 },
};
static struct clksrc_clk clk_hclk_psys = {
.clk = {
.name = "hclk_psys",
.id = -1,
},
.sources = &clkset_hclk_sys,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 24, .size = 4 },
};
static struct clksrc_clk clk_pclk_psys = {
.clk = {
.name = "pclk_psys",
.id = -1,
.parent = &clk_hclk_psys.clk,
},
.reg_div = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 },
};
static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
......@@ -51,176 +173,226 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
}
static struct clk clk_h200 = {
.name = "hclk200",
static int s5pv210_clk_ip4_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_IP4, clk, enable);
}
static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);
}
static struct clk clk_sclk_hdmi27m = {
.name = "sclk_hdmi27m",
.id = -1,
.rate = 27000000,
};
static struct clk clk_h100 = {
.name = "hclk100",
static struct clk clk_sclk_hdmiphy = {
.name = "sclk_hdmiphy",
.id = -1,
};
static struct clk clk_h166 = {
.name = "hclk166",
static struct clk clk_sclk_usbphy0 = {
.name = "sclk_usbphy0",
.id = -1,
};
static struct clk clk_h133 = {
.name = "hclk133",
static struct clk clk_sclk_usbphy1 = {
.name = "sclk_usbphy1",
.id = -1,
};
static struct clk clk_p100 = {
.name = "pclk100",
static struct clk clk_pcmcdclk0 = {
.name = "pcmcdclk",
.id = -1,
};
static struct clk clk_p83 = {
.name = "pclk83",
static struct clk clk_pcmcdclk1 = {
.name = "pcmcdclk",
.id = -1,
};
static struct clk clk_p66 = {
.name = "pclk66",
static struct clk clk_pcmcdclk2 = {
.name = "pcmcdclk",
.id = -1,
};
static struct clk *sys_clks[] = {
&clk_h200,
&clk_h100,
&clk_h166,
&clk_h133,
&clk_p100,
&clk_p83,
&clk_p66
static struct clk *clkset_vpllsrc_list[] = {
[0] = &clk_fin_vpll,
[1] = &clk_sclk_hdmi27m,
};
static struct clksrc_sources clkset_vpllsrc = {
.sources = clkset_vpllsrc_list,
.nr_sources = ARRAY_SIZE(clkset_vpllsrc_list),
};
static struct clksrc_clk clk_vpllsrc = {
.clk = {
.name = "vpll_src",
.id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 7),
},
.sources = &clkset_vpllsrc,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 28, .size = 1 },
};
static struct clk *clkset_sclk_vpll_list[] = {
[0] = &clk_vpllsrc.clk,
[1] = &clk_fout_vpll,
};
static struct clksrc_sources clkset_sclk_vpll = {
.sources = clkset_sclk_vpll_list,
.nr_sources = ARRAY_SIZE(clkset_sclk_vpll_list),
};
static struct clksrc_clk clk_sclk_vpll = {
.clk = {
.name = "sclk_vpll",
.id = -1,
},
.sources = &clkset_sclk_vpll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
};
static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 2;
}
static struct clk_ops clk_hclk_imem_ops = {
.get_rate = s5pv210_clk_imem_get_rate,
};
static struct clk init_clocks_disable[] = {
{
.name = "rot",
.id = -1,
.parent = &clk_h166,
.parent = &clk_hclk_dsys.clk,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1<<29),
}, {
.name = "otg",
.id = -1,
.parent = &clk_h133,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1<<16),
}, {
.name = "usb-host",
.id = -1,
.parent = &clk_h133,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1<<17),
}, {
.name = "lcd",
.id = -1,
.parent = &clk_h166,
.parent = &clk_hclk_dsys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1<<0),
}, {
.name = "cfcon",
.id = 0,
.parent = &clk_h133,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1<<25),
}, {
.name = "hsmmc",
.id = 0,
.parent = &clk_h133,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<16),
}, {
.name = "hsmmc",
.id = 1,
.parent = &clk_h133,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<17),
}, {
.name = "hsmmc",
.id = 2,
.parent = &clk_h133,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<18),
}, {
.name = "hsmmc",
.id = 3,
.parent = &clk_h133,
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<19),
}, {
.name = "systimer",
.id = -1,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<16),
}, {
.name = "watchdog",
.id = -1,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<22),
}, {
.name = "rtc",
.id = -1,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<15),
}, {
.name = "i2c",
.id = 0,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<7),
}, {
.name = "i2c",
.id = 1,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<8),
}, {
.name = "i2c",
.id = 2,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<9),
}, {
.name = "spi",
.id = 0,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<12),
}, {
.name = "spi",
.id = 1,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<13),
}, {
.name = "spi",
.id = 2,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<14),
}, {
.name = "timers",
.id = -1,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<23),
}, {
.name = "adc",
.id = -1,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<24),
}, {
.name = "keypad",
.id = -1,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<21),
}, {
......@@ -246,106 +418,537 @@ static struct clk init_clocks_disable[] = {
static struct clk init_clocks[] = {
{
.name = "hclk_imem",
.id = -1,
.parent = &clk_hclk_msys.clk,
.ctrlbit = (1 << 5),
.enable = s5pv210_clk_ip0_ctrl,
.ops = &clk_hclk_imem_ops,
}, {
.name = "uart",
.id = 0,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<7),
}, {
.name = "uart",
.id = 1,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<8),
}, {
.name = "uart",
.id = 2,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<9),
}, {
.name = "uart",
.id = 3,
.parent = &clk_p66,
.parent = &clk_pclk_psys.clk,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<10),
},
};
static struct clksrc_clk clk_mout_apll = {
.clk = {
.name = "mout_apll",
static struct clk *clkset_uart_list[] = {
[6] = &clk_mout_mpll.clk,
[7] = &clk_mout_epll.clk,
};
static struct clksrc_sources clkset_uart = {
.sources = clkset_uart_list,
.nr_sources = ARRAY_SIZE(clkset_uart_list),
};
static struct clk *clkset_group1_list[] = {
[0] = &clk_sclk_a2m.clk,
[1] = &clk_mout_mpll.clk,
[2] = &clk_mout_epll.clk,
[3] = &clk_sclk_vpll.clk,
};
static struct clksrc_sources clkset_group1 = {
.sources = clkset_group1_list,
.nr_sources = ARRAY_SIZE(clkset_group1_list),
};
static struct clk *clkset_sclk_onenand_list[] = {
[0] = &clk_hclk_psys.clk,
[1] = &clk_hclk_dsys.clk,
};
static struct clksrc_sources clkset_sclk_onenand = {
.sources = clkset_sclk_onenand_list,
.nr_sources = ARRAY_SIZE(clkset_sclk_onenand_list),
};
static struct clk *clkset_sclk_dac_list[] = {
[0] = &clk_sclk_vpll.clk,
[1] = &clk_sclk_hdmiphy,
};
static struct clksrc_sources clkset_sclk_dac = {
.sources = clkset_sclk_dac_list,
.nr_sources = ARRAY_SIZE(clkset_sclk_dac_list),
};
static struct clksrc_clk clk_sclk_dac = {
.clk = {
.name = "sclk_dac",
.id = -1,
.ctrlbit = (1 << 10),
.enable = s5pv210_clk_ip1_ctrl,
},
.sources = &clk_src_apll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
.sources = &clkset_sclk_dac,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 1 },
};
static struct clksrc_clk clk_mout_epll = {
.clk = {
.name = "mout_epll",
static struct clksrc_clk clk_sclk_pixel = {
.clk = {
.name = "sclk_pixel",
.id = -1,
.parent = &clk_sclk_vpll.clk,
},
.sources = &clk_src_epll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4},
};
static struct clksrc_clk clk_mout_mpll = {
.clk = {
.name = "mout_mpll",
static struct clk *clkset_sclk_hdmi_list[] = {
[0] = &clk_sclk_pixel.clk,
[1] = &clk_sclk_hdmiphy,
};
static struct clksrc_sources clkset_sclk_hdmi = {
.sources = clkset_sclk_hdmi_list,
.nr_sources = ARRAY_SIZE(clkset_sclk_hdmi_list),
};
static struct clksrc_clk clk_sclk_hdmi = {
.clk = {
.name = "sclk_hdmi",
.id = -1,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1 << 11),
},
.sources = &clk_src_mpll,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
.sources = &clkset_sclk_hdmi,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
};
static struct clk *clkset_uart_list[] = {
static struct clk *clkset_sclk_mixer_list[] = {
[0] = &clk_sclk_dac.clk,
[1] = &clk_sclk_hdmi.clk,
};
static struct clksrc_sources clkset_sclk_mixer = {
.sources = clkset_sclk_mixer_list,
.nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list),
};
static struct clk *clkset_sclk_audio0_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_pcmcdclk0,
[2] = &clk_sclk_hdmi27m,
[3] = &clk_sclk_usbphy0,
[4] = &clk_sclk_usbphy1,
[5] = &clk_sclk_hdmiphy,
[6] = &clk_mout_mpll.clk,
[7] = &clk_mout_epll.clk,
[8] = &clk_sclk_vpll.clk,
};
static struct clksrc_sources clkset_uart = {
.sources = clkset_uart_list,
.nr_sources = ARRAY_SIZE(clkset_uart_list),
static struct clksrc_sources clkset_sclk_audio0 = {
.sources = clkset_sclk_audio0_list,
.nr_sources = ARRAY_SIZE(clkset_sclk_audio0_list),
};
static struct clksrc_clk clk_sclk_audio0 = {
.clk = {
.name = "sclk_audio",
.id = 0,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 4),
},
.sources = &clkset_sclk_audio0,
.reg_src = { .reg = S5P_CLK_SRC6, .shift = 0, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV6, .shift = 0, .size = 4 },
};
static struct clk *clkset_sclk_audio1_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_pcmcdclk1,
[2] = &clk_sclk_hdmi27m,
[3] = &clk_sclk_usbphy0,
[4] = &clk_sclk_usbphy1,
[5] = &clk_sclk_hdmiphy,
[6] = &clk_mout_mpll.clk,
[7] = &clk_mout_epll.clk,
[8] = &clk_sclk_vpll.clk,
};
static struct clksrc_sources clkset_sclk_audio1 = {
.sources = clkset_sclk_audio1_list,
.nr_sources = ARRAY_SIZE(clkset_sclk_audio1_list),
};
static struct clksrc_clk clk_sclk_audio1 = {
.clk = {
.name = "sclk_audio",
.id = 1,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 5),
},
.sources = &clkset_sclk_audio1,
.reg_src = { .reg = S5P_CLK_SRC6, .shift = 4, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV6, .shift = 4, .size = 4 },
};
static struct clk *clkset_sclk_audio2_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_pcmcdclk0,
[2] = &clk_sclk_hdmi27m,
[3] = &clk_sclk_usbphy0,
[4] = &clk_sclk_usbphy1,
[5] = &clk_sclk_hdmiphy,
[6] = &clk_mout_mpll.clk,
[7] = &clk_mout_epll.clk,
[8] = &clk_sclk_vpll.clk,
};
static struct clksrc_sources clkset_sclk_audio2 = {
.sources = clkset_sclk_audio2_list,
.nr_sources = ARRAY_SIZE(clkset_sclk_audio2_list),
};
static struct clksrc_clk clk_sclk_audio2 = {
.clk = {
.name = "sclk_audio",
.id = 2,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 6),
},
.sources = &clkset_sclk_audio2,
.reg_src = { .reg = S5P_CLK_SRC6, .shift = 8, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV6, .shift = 8, .size = 4 },
};
static struct clk *clkset_sclk_spdif_list[] = {
[0] = &clk_sclk_audio0.clk,
[1] = &clk_sclk_audio1.clk,
[2] = &clk_sclk_audio2.clk,
};
static struct clksrc_sources clkset_sclk_spdif = {
.sources = clkset_sclk_spdif_list,
.nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list),
};
static struct clk *clkset_group2_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_xusbxti,
[2] = &clk_sclk_hdmi27m,
[3] = &clk_sclk_usbphy0,
[4] = &clk_sclk_usbphy1,
[5] = &clk_sclk_hdmiphy,
[6] = &clk_mout_mpll.clk,
[7] = &clk_mout_epll.clk,
[8] = &clk_sclk_vpll.clk,
};
static struct clksrc_sources clkset_group2 = {
.sources = clkset_group2_list,
.nr_sources = ARRAY_SIZE(clkset_group2_list),
};
static struct clksrc_clk clksrcs[] = {
{
.clk = {
.name = "uclk1",
.name = "sclk_dmc",
.id = -1,
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
}, {
.clk = {
.name = "sclk_onenand",
.id = -1,
},
.sources = &clkset_sclk_onenand,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 28, .size = 1 },
.reg_div = { .reg = S5P_CLK_DIV6, .shift = 12, .size = 3 },
}, {
.clk = {
.name = "uclk1",
.id = 0,
.ctrlbit = (1<<17),
.enable = s5pv210_clk_ip3_ctrl,
},
.sources = &clkset_uart,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
}
}, {
.clk = {
.name = "uclk1",
.id = 1,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 18),
},
.sources = &clkset_uart,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
}, {
.clk = {
.name = "uclk1",
.id = 2,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 19),
},
.sources = &clkset_uart,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 },
}, {
.clk = {
.name = "uclk1",
.id = 3,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 20),
},
.sources = &clkset_uart,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
}, {
.clk = {
.name = "sclk_mixer",
.id = -1,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1 << 9),
},
.sources = &clkset_sclk_mixer,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
}, {
.clk = {
.name = "sclk_spdif",
.id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 27),
},
.sources = &clkset_sclk_spdif,
.reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
}, {
.clk = {
.name = "sclk_fimc",
.id = 0,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 24),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
}, {
.clk = {
.name = "sclk_fimc",
.id = 1,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 25),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 },
}, {
.clk = {
.name = "sclk_fimc",
.id = 2,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 26),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 },
}, {
.clk = {
.name = "sclk_cam",
.id = 0,
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
}, {
.clk = {
.name = "sclk_cam",
.id = 1,
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 4 },
}, {
.clk = {
.name = "sclk_fimd",
.id = -1,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1 << 0),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.id = 0,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1 << 16),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 0, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.id = 1,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1 << 17),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 4, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.id = 2,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1 << 18),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 8, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 8, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.id = 3,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1 << 19),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 12, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
}, {
.clk = {
.name = "sclk_mfc",
.id = -1,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 16),
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_g2d",
.id = -1,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 12),
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
}, {
.clk = {
.name = "sclk_g3d",
.id = -1,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 8),
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_csis",
.id = -1,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 31),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 28, .size = 4 },
}, {
.clk = {
.name = "sclk_spi",
.id = 0,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 12),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_spi",
.id = 1,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 13),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_pwi",
.id = -1,
.enable = &s5pv210_clk_ip4_ctrl,
.ctrlbit = (1 << 2),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC6, .shift = 20, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV6, .shift = 24, .size = 4 },
}, {
.clk = {
.name = "sclk_pwm",
.id = -1,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 23),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC5, .shift = 12, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV5, .shift = 12, .size = 4 },
},
};
/* Clock initialisation code */
static struct clksrc_clk *init_parents[] = {
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
&clk_mout_epll,
&clk_mout_mpll,
&clk_armclk,
&clk_hclk_msys,
&clk_sclk_a2m,
&clk_hclk_dsys,
&clk_hclk_psys,
&clk_pclk_msys,
&clk_pclk_dsys,
&clk_pclk_psys,
&clk_vpllsrc,
&clk_sclk_vpll,
&clk_sclk_dac,
&clk_sclk_pixel,
&clk_sclk_hdmi,
};
#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
void __init_or_cpufreq s5pv210_setup_clocks(void)
{
struct clk *xtal_clk;
unsigned long xtal;
unsigned long vpllsrc;
unsigned long armclk;
unsigned long hclk200;
unsigned long hclk166;
unsigned long hclk133;
unsigned long pclk100;
unsigned long pclk83;
unsigned long pclk66;
unsigned long hclk_msys;
unsigned long hclk_dsys;
unsigned long hclk_psys;
unsigned long pclk_msys;
unsigned long pclk_dsys;
unsigned long pclk_psys;
unsigned long apll;
unsigned long mpll;
unsigned long epll;
unsigned long vpll;
unsigned int ptr;
u32 clkdiv0, clkdiv1;
......@@ -368,59 +971,46 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500);
printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld",
apll, mpll, epll);
armclk = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_APLL);
if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX200_MASK)
hclk200 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200);
else
hclk200 = armclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200);
if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX166_MASK) {
hclk166 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M);
hclk166 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166);
} else
hclk166 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166);
if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX133_MASK) {
hclk133 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M);
hclk133 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133);
} else
hclk133 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133);
pclk100 = hclk200 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK100);
pclk83 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83);
pclk66 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66);
printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld, \
HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
armclk, hclk200, hclk166, hclk133, pclk100, pclk83, pclk66);
vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502);
clk_fout_apll.rate = apll;
clk_fout_mpll.rate = mpll;
clk_fout_epll.rate = epll;
clk_fout_vpll.rate = vpll;
clk_f.rate = armclk;
clk_h.rate = hclk133;
clk_p.rate = pclk66;
clk_p66.rate = pclk66;
clk_p83.rate = pclk83;
clk_h133.rate = hclk133;
clk_h166.rate = hclk166;
clk_h200.rate = hclk200;
printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
apll, mpll, epll, vpll);
armclk = clk_get_rate(&clk_armclk.clk);
hclk_msys = clk_get_rate(&clk_hclk_msys.clk);
hclk_dsys = clk_get_rate(&clk_hclk_dsys.clk);
hclk_psys = clk_get_rate(&clk_hclk_psys.clk);
pclk_msys = clk_get_rate(&clk_pclk_msys.clk);
pclk_dsys = clk_get_rate(&clk_pclk_dsys.clk);
pclk_psys = clk_get_rate(&clk_pclk_psys.clk);
printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n"
"HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
armclk, hclk_msys, hclk_dsys, hclk_psys,
pclk_msys, pclk_dsys, pclk_psys);
for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
s3c_set_clksrc(init_parents[ptr], true);
clk_f.rate = armclk;
clk_h.rate = hclk_psys;
clk_p.rate = pclk_psys;
for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
s3c_set_clksrc(&clksrcs[ptr], true);
}
static struct clk *clks[] __initdata = {
&clk_mout_epll.clk,
&clk_mout_mpll.clk,
&clk_sclk_hdmi27m,
&clk_sclk_hdmiphy,
&clk_sclk_usbphy0,
&clk_sclk_usbphy1,
&clk_pcmcdclk0,
&clk_pcmcdclk1,
&clk_pcmcdclk2,
};
void __init s5pv210_register_clocks(void)
......@@ -433,13 +1023,12 @@ void __init s5pv210_register_clocks(void)
if (ret > 0)
printk(KERN_ERR "Failed to register %u clocks\n", ret);
for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
s3c_register_clksrc(sysclks[ptr], 1);
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
ret = s3c24xx_register_clocks(sys_clks, ARRAY_SIZE(sys_clks));
if (ret > 0)
printk(KERN_ERR "Failed to register system clocks\n");
clkp = init_clocks_disable;
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
ret = s3c24xx_register_clock(clkp);
......
......@@ -100,7 +100,7 @@ void __init s5pv210_init_irq(void)
s5p_init_irq(vic, ARRAY_SIZE(vic));
}
static struct sysdev_class s5pv210_sysclass = {
struct sysdev_class s5pv210_sysclass = {
.name = "s5pv210-core",
};
......
/* linux/arch/arm/mach-s5pv210/dev-audio.c
*
* 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 version 2 as
* published by the Free Software Foundation.
*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <plat/gpio-cfg.h>
#include <plat/audio.h>
#include <mach/gpio.h>
#include <mach/map.h>
#include <mach/dma.h>
#include <mach/irqs.h>
static int s5pv210_cfg_i2s(struct platform_device *pdev)
{
/* configure GPIO for i2s port */
switch (pdev->id) {
case 1:
s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(2));
break;
case 2:
s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(4));
s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(4));
s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(4));
s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(4));
s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(4));
break;
case -1:
s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPI(5), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPI(6), S3C_GPIO_SFN(2));
break;
default:
printk(KERN_ERR "Invalid Device %d\n", pdev->id);
return -EINVAL;
}
return 0;
}
static struct s3c_audio_pdata s3c_i2s_pdata = {
.cfg_gpio = s5pv210_cfg_i2s,
};
static struct resource s5pv210_iis0_resource[] = {
[0] = {
.start = S5PV210_PA_IIS0,
.end = S5PV210_PA_IIS0 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_I2S0_TX,
.end = DMACH_I2S0_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_I2S0_RX,
.end = DMACH_I2S0_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5pv210_device_iis0 = {
.name = "s3c64xx-iis-v4",
.id = -1,
.num_resources = ARRAY_SIZE(s5pv210_iis0_resource),
.resource = s5pv210_iis0_resource,
.dev = {
.platform_data = &s3c_i2s_pdata,
},
};
static struct resource s5pv210_iis1_resource[] = {
[0] = {
.start = S5PV210_PA_IIS1,
.end = S5PV210_PA_IIS1 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_I2S1_TX,
.end = DMACH_I2S1_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_I2S1_RX,
.end = DMACH_I2S1_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5pv210_device_iis1 = {
.name = "s3c64xx-iis",
.id = 1,
.num_resources = ARRAY_SIZE(s5pv210_iis1_resource),
.resource = s5pv210_iis1_resource,
.dev = {
.platform_data = &s3c_i2s_pdata,
},
};
static struct resource s5pv210_iis2_resource[] = {
[0] = {
.start = S5PV210_PA_IIS2,
.end = S5PV210_PA_IIS2 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_I2S2_TX,
.end = DMACH_I2S2_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_I2S2_RX,
.end = DMACH_I2S2_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5pv210_device_iis2 = {
.name = "s3c64xx-iis",
.id = 2,
.num_resources = ARRAY_SIZE(s5pv210_iis2_resource),
.resource = s5pv210_iis2_resource,
.dev = {
.platform_data = &s3c_i2s_pdata,
},
};
/* PCM Controller platform_devices */
static int s5pv210_pcm_cfg_gpio(struct platform_device *pdev)
{
switch (pdev->id) {
case 0:
s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(3));
break;
case 1:
s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(3));
s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(3));
break;
case 2:
s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(2));
s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(2));
break;
default:
printk(KERN_DEBUG "Invalid PCM Controller number!");
return -EINVAL;
}
return 0;
}
static struct s3c_audio_pdata s3c_pcm_pdata = {
.cfg_gpio = s5pv210_pcm_cfg_gpio,
};
static struct resource s5pv210_pcm0_resource[] = {
[0] = {
.start = S5PV210_PA_PCM0,
.end = S5PV210_PA_PCM0 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_PCM0_TX,
.end = DMACH_PCM0_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_PCM0_RX,
.end = DMACH_PCM0_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5pv210_device_pcm0 = {
.name = "samsung-pcm",
.id = 0,
.num_resources = ARRAY_SIZE(s5pv210_pcm0_resource),
.resource = s5pv210_pcm0_resource,
.dev = {
.platform_data = &s3c_pcm_pdata,
},
};
static struct resource s5pv210_pcm1_resource[] = {
[0] = {
.start = S5PV210_PA_PCM1,
.end = S5PV210_PA_PCM1 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_PCM1_TX,
.end = DMACH_PCM1_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_PCM1_RX,
.end = DMACH_PCM1_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5pv210_device_pcm1 = {
.name = "samsung-pcm",
.id = 1,
.num_resources = ARRAY_SIZE(s5pv210_pcm1_resource),
.resource = s5pv210_pcm1_resource,
.dev = {
.platform_data = &s3c_pcm_pdata,
},
};
static struct resource s5pv210_pcm2_resource[] = {
[0] = {
.start = S5PV210_PA_PCM2,
.end = S5PV210_PA_PCM2 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_PCM2_TX,
.end = DMACH_PCM2_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_PCM2_RX,
.end = DMACH_PCM2_RX,
.flags = IORESOURCE_DMA,
},
};
struct platform_device s5pv210_device_pcm2 = {
.name = "samsung-pcm",
.id = 2,
.num_resources = ARRAY_SIZE(s5pv210_pcm2_resource),
.resource = s5pv210_pcm2_resource,
.dev = {
.platform_data = &s3c_pcm_pdata,
},
};
/* AC97 Controller platform devices */
static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev)
{
s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(4));
s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(4));
s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(4));
s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(4));
s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(4));
return 0;
}
static struct resource s5pv210_ac97_resource[] = {
[0] = {
.start = S5PV210_PA_AC97,
.end = S5PV210_PA_AC97 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_AC97_PCMOUT,
.end = DMACH_AC97_PCMOUT,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_AC97_PCMIN,
.end = DMACH_AC97_PCMIN,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = DMACH_AC97_MICIN,
.end = DMACH_AC97_MICIN,
.flags = IORESOURCE_DMA,
},
[4] = {
.start = IRQ_AC97,
.end = IRQ_AC97,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c_audio_pdata s3c_ac97_pdata = {
.cfg_gpio = s5pv210_ac97_cfg_gpio,
};
static u64 s5pv210_ac97_dmamask = DMA_BIT_MASK(32);
struct platform_device s5pv210_device_ac97 = {
.name = "s3c-ac97",
.id = -1,
.num_resources = ARRAY_SIZE(s5pv210_ac97_resource),
.resource = s5pv210_ac97_resource,
.dev = {
.platform_data = &s3c_ac97_pdata,
.dma_mask = &s5pv210_ac97_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
/*
* 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.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <plat/devs.h>
#include <plat/irqs.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include <plat/s3c-pl330-pdata.h>
static u64 dma_dmamask = DMA_BIT_MASK(32);
static struct resource s5pv210_pdma0_resource[] = {
[0] = {
.start = S5PV210_PA_PDMA0,
.end = S5PV210_PA_PDMA0 + SZ_4K,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_PDMA0,
.end = IRQ_PDMA0,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
.peri = {
[0] = DMACH_UART0_RX,
[1] = DMACH_UART0_TX,
[2] = DMACH_UART1_RX,
[3] = DMACH_UART1_TX,
[4] = DMACH_UART2_RX,
[5] = DMACH_UART2_TX,
[6] = DMACH_UART3_RX,
[7] = DMACH_UART3_TX,
[8] = DMACH_MAX,
[9] = DMACH_I2S0_RX,
[10] = DMACH_I2S0_TX,
[11] = DMACH_I2S0S_TX,
[12] = DMACH_I2S1_RX,
[13] = DMACH_I2S1_TX,
[14] = DMACH_MAX,
[15] = DMACH_MAX,
[16] = DMACH_SPI0_RX,
[17] = DMACH_SPI0_TX,
[18] = DMACH_SPI1_RX,
[19] = DMACH_SPI1_TX,
[20] = DMACH_MAX,
[21] = DMACH_MAX,
[22] = DMACH_AC97_MICIN,
[23] = DMACH_AC97_PCMIN,
[24] = DMACH_AC97_PCMOUT,
[25] = DMACH_MAX,
[26] = DMACH_PWM,
[27] = DMACH_SPDIF,
[28] = DMACH_MAX,
[29] = DMACH_MAX,
[30] = DMACH_MAX,
[31] = DMACH_MAX,
},
};
static struct platform_device s5pv210_device_pdma0 = {
.name = "s3c-pl330",
.id = 1,
.num_resources = ARRAY_SIZE(s5pv210_pdma0_resource),
.resource = s5pv210_pdma0_resource,
.dev = {
.dma_mask = &dma_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s5pv210_pdma0_pdata,
},
};
static struct resource s5pv210_pdma1_resource[] = {
[0] = {
.start = S5PV210_PA_PDMA1,
.end = S5PV210_PA_PDMA1 + SZ_4K,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_PDMA1,
.end = IRQ_PDMA1,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
.peri = {
[0] = DMACH_UART0_RX,
[1] = DMACH_UART0_TX,
[2] = DMACH_UART1_RX,
[3] = DMACH_UART1_TX,
[4] = DMACH_UART2_RX,
[5] = DMACH_UART2_TX,
[6] = DMACH_UART3_RX,
[7] = DMACH_UART3_TX,
[8] = DMACH_MAX,
[9] = DMACH_I2S0_RX,
[10] = DMACH_I2S0_TX,
[11] = DMACH_I2S0S_TX,
[12] = DMACH_I2S1_RX,
[13] = DMACH_I2S1_TX,
[14] = DMACH_I2S2_RX,
[15] = DMACH_I2S2_TX,
[16] = DMACH_SPI0_RX,
[17] = DMACH_SPI0_TX,
[18] = DMACH_SPI1_RX,
[19] = DMACH_SPI1_TX,
[20] = DMACH_MAX,
[21] = DMACH_MAX,
[22] = DMACH_PCM0_RX,
[23] = DMACH_PCM0_TX,
[24] = DMACH_PCM1_RX,
[25] = DMACH_PCM1_TX,
[26] = DMACH_MSM_REQ0,
[27] = DMACH_MSM_REQ1,
[28] = DMACH_MSM_REQ2,
[29] = DMACH_MSM_REQ3,
[30] = DMACH_PCM2_RX,
[31] = DMACH_PCM2_TX,
},
};
static struct platform_device s5pv210_device_pdma1 = {
.name = "s3c-pl330",
.id = 2,
.num_resources = ARRAY_SIZE(s5pv210_pdma1_resource),
.resource = s5pv210_pdma1_resource,
.dev = {
.dma_mask = &dma_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s5pv210_pdma1_pdata,
},
};
static struct platform_device *s5pv210_dmacs[] __initdata = {
&s5pv210_device_pdma0,
&s5pv210_device_pdma1,
};
static int __init s5pv210_dma_init(void)
{
platform_add_devices(s5pv210_dmacs, ARRAY_SIZE(s5pv210_dmacs));
return 0;
}
arch_initcall(s5pv210_dma_init);
/* linux/arch/arm/mach-s5pv210/gpiolib.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S5PV210 - GPIOlib 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/irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
#include <mach/map.h>
static struct s3c_gpio_cfg gpio_cfg = {
.set_config = s3c_gpio_setcfg_s3c64xx_4bit,
.set_pull = s3c_gpio_setpull_updown,
.get_pull = s3c_gpio_getpull_updown,
};
static struct s3c_gpio_cfg gpio_cfg_noint = {
.set_config = s3c_gpio_setcfg_s3c64xx_4bit,
.set_pull = s3c_gpio_setpull_updown,
.get_pull = s3c_gpio_getpull_updown,
};
/* GPIO bank's base address given the index of the bank in the
* list of all gpio banks.
*/
#define S5PV210_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20))
/*
* Following are the gpio banks in v210.
*
* The 'config' member when left to NULL, is initialized to the default
* structure gpio_cfg in the init function below.
*
* The 'base' member is also initialized in the init function below.
* Note: The initialization of 'base' member of s3c_gpio_chip structure
* uses the above macro and depends on the banks being listed in order here.
*/
static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
{
.chip = {
.base = S5PV210_GPA0(0),
.ngpio = S5PV210_GPIO_A0_NR,
.label = "GPA0",
},
}, {
.chip = {
.base = S5PV210_GPA1(0),
.ngpio = S5PV210_GPIO_A1_NR,
.label = "GPA1",
},
}, {
.chip = {
.base = S5PV210_GPB(0),
.ngpio = S5PV210_GPIO_B_NR,
.label = "GPB",
},
}, {
.chip = {
.base = S5PV210_GPC0(0),
.ngpio = S5PV210_GPIO_C0_NR,
.label = "GPC0",
},
}, {
.chip = {
.base = S5PV210_GPC1(0),
.ngpio = S5PV210_GPIO_C1_NR,
.label = "GPC1",
},
}, {
.chip = {
.base = S5PV210_GPD0(0),
.ngpio = S5PV210_GPIO_D0_NR,
.label = "GPD0",
},
}, {
.chip = {
.base = S5PV210_GPD1(0),
.ngpio = S5PV210_GPIO_D1_NR,
.label = "GPD1",
},
}, {
.chip = {
.base = S5PV210_GPE0(0),
.ngpio = S5PV210_GPIO_E0_NR,
.label = "GPE0",
},
}, {
.chip = {
.base = S5PV210_GPE1(0),
.ngpio = S5PV210_GPIO_E1_NR,
.label = "GPE1",
},
}, {
.chip = {
.base = S5PV210_GPF0(0),
.ngpio = S5PV210_GPIO_F0_NR,
.label = "GPF0",
},
}, {
.chip = {
.base = S5PV210_GPF1(0),
.ngpio = S5PV210_GPIO_F1_NR,
.label = "GPF1",
},
}, {
.chip = {
.base = S5PV210_GPF2(0),
.ngpio = S5PV210_GPIO_F2_NR,
.label = "GPF2",
},
}, {
.chip = {
.base = S5PV210_GPF3(0),
.ngpio = S5PV210_GPIO_F3_NR,
.label = "GPF3",
},
}, {
.chip = {
.base = S5PV210_GPG0(0),
.ngpio = S5PV210_GPIO_G0_NR,
.label = "GPG0",
},
}, {
.chip = {
.base = S5PV210_GPG1(0),
.ngpio = S5PV210_GPIO_G1_NR,
.label = "GPG1",
},
}, {
.chip = {
.base = S5PV210_GPG2(0),
.ngpio = S5PV210_GPIO_G2_NR,
.label = "GPG2",
},
}, {
.chip = {
.base = S5PV210_GPG3(0),
.ngpio = S5PV210_GPIO_G3_NR,
.label = "GPG3",
},
}, {
.chip = {
.base = S5PV210_GPI(0),
.ngpio = S5PV210_GPIO_I_NR,
.label = "GPI",
},
}, {
.chip = {
.base = S5PV210_GPJ0(0),
.ngpio = S5PV210_GPIO_J0_NR,
.label = "GPJ0",
},
}, {
.chip = {
.base = S5PV210_GPJ1(0),
.ngpio = S5PV210_GPIO_J1_NR,
.label = "GPJ1",
},
}, {
.chip = {
.base = S5PV210_GPJ2(0),
.ngpio = S5PV210_GPIO_J2_NR,
.label = "GPJ2",
},
}, {
.chip = {
.base = S5PV210_GPJ3(0),
.ngpio = S5PV210_GPIO_J3_NR,
.label = "GPJ3",
},
}, {
.chip = {
.base = S5PV210_GPJ4(0),
.ngpio = S5PV210_GPIO_J4_NR,
.label = "GPJ4",
},
}, {
.config = &gpio_cfg_noint,
.chip = {
.base = S5PV210_MP01(0),
.ngpio = S5PV210_GPIO_MP01_NR,
.label = "MP01",
},
}, {
.config = &gpio_cfg_noint,
.chip = {
.base = S5PV210_MP02(0),
.ngpio = S5PV210_GPIO_MP02_NR,
.label = "MP02",
},
}, {
.config = &gpio_cfg_noint,
.chip = {
.base = S5PV210_MP03(0),
.ngpio = S5PV210_GPIO_MP03_NR,
.label = "MP03",
},
}, {
.base = (S5P_VA_GPIO + 0xC00),
.config = &gpio_cfg_noint,
.chip = {
.base = S5PV210_GPH0(0),
.ngpio = S5PV210_GPIO_H0_NR,
.label = "GPH0",
},
}, {
.base = (S5P_VA_GPIO + 0xC20),
.config = &gpio_cfg_noint,
.chip = {
.base = S5PV210_GPH1(0),
.ngpio = S5PV210_GPIO_H1_NR,
.label = "GPH1",
},
}, {
.base = (S5P_VA_GPIO + 0xC40),
.config = &gpio_cfg_noint,
.chip = {
.base = S5PV210_GPH2(0),
.ngpio = S5PV210_GPIO_H2_NR,
.label = "GPH2",
},
}, {
.base = (S5P_VA_GPIO + 0xC60),
.config = &gpio_cfg_noint,
.chip = {
.base = S5PV210_GPH3(0),
.ngpio = S5PV210_GPIO_H3_NR,
.label = "GPH3",
},
},
};
static __init int s5pv210_gpiolib_init(void)
{
struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
int i = 0;
for (i = 0; i < nr_chips; i++, chip++) {
if (chip->config == NULL)
chip->config = &gpio_cfg;
if (chip->base == NULL)
chip->base = S5PV210_BANK_BASE(i);
}
samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
return 0;
}
core_initcall(s5pv210_gpiolib_init);
/*
* 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.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MACH_DMA_H
#define __MACH_DMA_H
/* This platform uses the common S3C DMA API driver for PL330 */
#include <plat/s3c-dma-pl330.h>
#endif /* __MACH_DMA_H */
......@@ -18,6 +18,8 @@
#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq __gpio_to_irq
/* Practically, GPIO banks upto MP03 are the configurable gpio banks */
/* GPIO bank sizes */
#define S5PV210_GPIO_A0_NR (8)
#define S5PV210_GPIO_A1_NR (4)
......@@ -47,6 +49,10 @@
#define S5PV210_GPIO_J3_NR (8)
#define S5PV210_GPIO_J4_NR (5)
#define S5PV210_GPIO_MP01_NR (8)
#define S5PV210_GPIO_MP02_NR (4)
#define S5PV210_GPIO_MP03_NR (8)
/* GPIO bank numbers */
/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
......@@ -85,6 +91,9 @@ enum s5p_gpio_number {
S5PV210_GPIO_J2_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J1),
S5PV210_GPIO_J3_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J2),
S5PV210_GPIO_J4_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J3),
S5PV210_GPIO_MP01_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J4),
S5PV210_GPIO_MP02_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP01),
S5PV210_GPIO_MP03_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP02),
};
/* S5PV210 GPIO number definitions */
......@@ -115,13 +124,16 @@ enum s5p_gpio_number {
#define S5PV210_GPJ2(_nr) (S5PV210_GPIO_J2_START + (_nr))
#define S5PV210_GPJ3(_nr) (S5PV210_GPIO_J3_START + (_nr))
#define S5PV210_GPJ4(_nr) (S5PV210_GPIO_J4_START + (_nr))
#define S5PV210_MP01(_nr) (S5PV210_GPIO_MP01_START + (_nr))
#define S5PV210_MP02(_nr) (S5PV210_GPIO_MP02_START + (_nr))
#define S5PV210_MP03(_nr) (S5PV210_GPIO_MP03_START + (_nr))
/* the end of the S5PV210 specific gpios */
#define S5PV210_GPIO_END (S5PV210_GPJ4(S5PV210_GPIO_J4_NR) + 1)
#define S5PV210_GPIO_END (S5PV210_MP03(S5PV210_GPIO_MP03_NR) + 1)
#define S3C_GPIO_END S5PV210_GPIO_END
/* define the number of gpios we need to the one after the GPJ4() range */
#define ARCH_NR_GPIOS (S5PV210_GPJ4(S5PV210_GPIO_J4_NR) + \
/* define the number of gpios we need to the one after the MP03() range */
#define ARCH_NR_GPIOS (S5PV210_MP03(S5PV210_GPIO_MP03_NR) + \
CONFIG_SAMSUNG_GPIO_EXTRA + 1)
#include <asm-generic/gpio.h>
......
......@@ -43,6 +43,10 @@
#define S5PV210_PA_SROMC (0xE8000000)
#define S5PV210_PA_MDMA 0xFA200000
#define S5PV210_PA_PDMA0 0xE0900000
#define S5PV210_PA_PDMA1 0xE0A00000
#define S5PV210_PA_VIC0 (0xF2000000)
#define S5P_PA_VIC0 S5PV210_PA_VIC0
......@@ -58,6 +62,19 @@
#define S5PV210_PA_SDRAM (0x20000000)
#define S5P_PA_SDRAM S5PV210_PA_SDRAM
/* I2S */
#define S5PV210_PA_IIS0 0xEEE30000
#define S5PV210_PA_IIS1 0xE2100000
#define S5PV210_PA_IIS2 0xE2A00000
/* PCM */
#define S5PV210_PA_PCM0 0xE2300000
#define S5PV210_PA_PCM1 0xE1200000
#define S5PV210_PA_PCM2 0xE2B00000
/* AC97 */
#define S5PV210_PA_AC97 0xE2200000
/* compatibiltiy defines. */
#define S3C_PA_UART S5PV210_PA_UART
#define S3C_PA_IIC S5PV210_PA_IIC0
......
/* linux/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
*
* Copyright (c) 2009 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/
*
* Copyright (c) 2009 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* Based on arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
* Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
*
* S5PV210 - pwm clock and timer support
*
......@@ -21,14 +22,14 @@
/**
* pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
* @cfg: The timer TCFG1 register bits shifted down to 0.
* @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)
{
return tcfg == S3C2410_TCFG1_MUX_TCLK;
return tcfg == S3C64XX_TCFG1_MUX_TCLK;
}
/**
......@@ -40,7 +41,7 @@ static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
*/
static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
{
return 1 << (1 + tcfg1);
return 1 << tcfg1;
}
/**
......@@ -50,7 +51,7 @@ static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
*/
static inline unsigned int pwm_tdiv_has_div1(void)
{
return 0;
return 1;
}
/**
......@@ -61,9 +62,9 @@ static inline unsigned int pwm_tdiv_has_div1(void)
*/
static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
{
return ilog2(div) - 1;
return ilog2(div);
}
#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
#endif /* __ASM_ARCH_PWMCLK_H */
......@@ -72,6 +72,8 @@ static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
};
static struct platform_device *smdkc110_devices[] __initdata = {
&s5pv210_device_iis0,
&s5pv210_device_ac97,
};
static void __init smdkc110_map_io(void)
......
......@@ -72,6 +72,8 @@ static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
};
static struct platform_device *smdkv210_devices[] __initdata = {
&s5pv210_device_iis0,
&s5pv210_device_ac97,
};
static void __init smdkv210_map_io(void)
......
/* linux/arch/arm/mach-s5pv210/setup-i2c0.c
*
* Copyright (c) 2009 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* I2C0 GPIO configuration.
*
* Based on plat-s3c64xx/setup-i2c0.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/types.h>
struct platform_device; /* don't need the contents */
#include <plat/iic.h>
void s3c_i2c0_cfg_gpio(struct platform_device *dev)
{
/* Will be populated later */
}
......@@ -870,9 +870,10 @@ void __init reserve_node_zero(pg_data_t *pgdat)
if (machine_is_p720t())
res_size = 0x00014000;
/* H1940 and RX3715 need to reserve this for suspend */
/* H1940, RX3715 and RX1950 need to reserve this for suspend */
if (machine_is_h1940() || machine_is_rx3715()) {
if (machine_is_h1940() || machine_is_rx3715()
|| machine_is_rx1950()) {
reserve_bootmem_node(pgdat, 0x30003000, 0x1000,
BOOTMEM_DEFAULT);
reserve_bootmem_node(pgdat, 0x30081000, 0x1000,
......
......@@ -164,4 +164,9 @@ config S3C24XX_SIMTEC_AUDIO
help
Add audio devices for common Simtec S3C24XX boards
config S3C2410_SETUP_TS
bool
help
Compile in platform device definition for Samsung TouchScreen.
endif
......@@ -38,6 +38,7 @@ obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += s3c2410-cpufreq-utils.o
# device specific setup and/or initialisation
obj-$(CONFIG_ARCH_S3C2410) += setup-i2c.o
obj-$(CONFIG_S3C2410_SETUP_TS) += setup-ts.o
# SPI gpio central GPIO functions
......
......@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
......@@ -38,8 +39,7 @@
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/regs-spi.h>
#include <mach/ts.h>
#include <plat/ts.h>
/* Serial port registrations */
......@@ -149,10 +149,14 @@ void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
{
struct s3c2410fb_mach_info *npd;
npd = kmalloc(sizeof(*npd), GFP_KERNEL);
npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
if (npd) {
memcpy(npd, pd, sizeof(*npd));
s3c_device_lcd.dev.platform_data = npd;
npd->displays = kmemdup(pd->displays,
sizeof(struct s3c2410fb_display) * npd->num_displays,
GFP_KERNEL);
if (!npd->displays)
printk(KERN_ERR "no memory for LCD display data\n");
} else {
printk(KERN_ERR "no memory for LCD platform data\n");
}
......@@ -338,14 +342,6 @@ struct platform_device s3c_device_adc = {
.resource = s3c_adc_resource,
};
/* HWMON */
struct platform_device s3c_device_hwmon = {
.name = "s3c-hwmon",
.id = -1,
.dev.parent = &s3c_device_adc.dev,
};
/* SDI */
static struct resource s3c_sdi_resource[] = {
......@@ -371,7 +367,7 @@ struct platform_device s3c_device_sdi = {
EXPORT_SYMBOL(s3c_device_sdi);
void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
{
struct s3c24xx_mci_pdata *npd;
......
......@@ -1104,7 +1104,7 @@ EXPORT_SYMBOL(s3c2410_dma_config);
* devaddr: physical address of the source
*/
int s3c2410_dma_devconfig(int channel,
int s3c2410_dma_devconfig(unsigned int channel,
enum s3c2410_dmasrc source,
unsigned long devaddr)
{
......
......@@ -34,6 +34,8 @@
#include <mach/regs-gpio.h>
#include <plat/gpio-core.h>
/* gpiolib wrappers until these are totally eliminated */
void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
......@@ -68,10 +70,10 @@ EXPORT_SYMBOL(s3c2410_gpio_setpin);
unsigned int s3c2410_gpio_getpin(unsigned int pin)
{
void __iomem *base = S3C24XX_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
unsigned long offs = pin - chip->chip.base;
return __raw_readl(base + 0x04) & (1<< offs);
return __raw_readl(chip->base + 0x04) & (1<< offs);
}
EXPORT_SYMBOL(s3c2410_gpio_getpin);
......
/* linux/arch/arm/plat-s3c24xx/setup-ts.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* Based on S3C24XX setup for i2c device
*
* 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/gpio.h>
struct platform_device; /* don't need the contents */
#include <mach/hardware.h>
#include <mach/regs-gpio.h>
/**
* s3c24xx_ts_cfg_gpio - configure gpio for s3c2410 systems
*
* Configure the GPIO for the S3C2410 system, where we have external FETs
* connected to the device (later systems such as the S3C2440 integrate
* these into the device).
*/
void s3c24xx_ts_cfg_gpio(struct platform_device *dev)
{
s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON);
s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON);
s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON);
s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON);
}
......@@ -13,6 +13,7 @@ config PLAT_S5P
select NO_IOPORT
select ARCH_REQUIRE_GPIOLIB
select S3C_GPIO_TRACK
select S5P_GPIO_DRVSTR
select SAMSUNG_GPIOLIB_4BIT
select S3C_GPIO_CFG_S3C64XX
select S3C_GPIO_PULL_UPDOWN
......
......@@ -16,4 +16,3 @@ obj-y += dev-uart.o
obj-y += cpu.o
obj-y += clock.o
obj-y += irq.o
obj-y += setup-i2c0.o
......@@ -33,7 +33,12 @@ struct clk clk_ext_xtal_mux = {
.id = -1,
};
static struct clk s5p_clk_27m = {
struct clk clk_xusbxti = {
.name = "xusbxti",
.id = -1,
};
struct clk s5p_clk_27m = {
.name = "clk_27m",
.id = -1,
.rate = 27000000,
......@@ -69,6 +74,13 @@ struct clk clk_fout_epll = {
.ctrlbit = (1 << 31),
};
/* VPLL clock output */
struct clk clk_fout_vpll = {
.name = "fout_vpll",
.id = -1,
.ctrlbit = (1 << 31),
};
/* ARM clock */
struct clk clk_arm = {
.name = "armclk",
......@@ -133,6 +145,7 @@ static struct clk *s5p_clks[] __initdata = {
&clk_fout_apll,
&clk_fout_mpll,
&clk_fout_epll,
&clk_fout_vpll,
&clk_arm,
&clk_vpll,
};
......
......@@ -79,7 +79,7 @@
#define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x))
#define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x))
#define S5P_TIMER_IRQ(x) S5P_IRQ(11 + (x))
#define S5P_TIMER_IRQ(x) (11 + (x))
#define IRQ_TIMER0 S5P_TIMER_IRQ(0)
#define IRQ_TIMER1 S5P_TIMER_IRQ(1)
......
......@@ -81,3 +81,25 @@ static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
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;
}
......@@ -21,12 +21,16 @@
#define clk_fin_mpll clk_ext_xtal_mux
#define clk_fin_epll 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_mpll;
extern struct clk clk_fout_epll;
extern struct clk clk_fout_vpll;
extern struct clk clk_arm;
extern struct clk clk_vpll;
......
......@@ -16,9 +16,10 @@ config PLAT_S5PC1XX
select SAMSUNG_IRQ_VIC_TIMER
select S3C_GPIO_TRACK
select S3C_GPIO_PULL_UPDOWN
select S5P_GPIO_DRVSTR
select S3C_GPIO_CFG_S3C24XX
select S3C_GPIO_CFG_S3C64XX
select S5P_GPIO_CFG_S5PC1XX
select SAMSUNG_GPIOLIB_4BIT
help
Base platform code for any Samsung S5PC1XX device
......@@ -38,25 +39,6 @@ config CPU_S5PC100_CLOCK
# platform specific device setup
config S5PC1XX_SETUP_FB_24BPP
bool
help
Common setup code for S5PC1XX with an 24bpp RGB display helper.
config S5PC1XX_SETUP_I2C0
bool
default y
help
Common setup code for i2c bus 0.
Note, currently since i2c0 is always compiled, this setup helper
is always compiled with it.
config S5PC1XX_SETUP_I2C1
bool
help
Common setup code for i2c bus 1.
config S5PC1XX_SETUP_SDHCI_GPIO
bool
help
......
......@@ -13,9 +13,8 @@ obj- :=
obj-y += dev-uart.o
obj-y += cpu.o
obj-y += irq.o irq-gpio.o irq-eint.o
obj-y += irq.o
obj-y += clock.o
obj-y += gpiolib.o
# CPU support
......@@ -24,8 +23,4 @@ obj-$(CONFIG_CPU_S5PC100_CLOCK) += s5pc100-clock.o
# Device setup
obj-$(CONFIG_S5P_GPIO_CFG_S5PC1XX) += gpio-config.o
obj-$(CONFIG_S5PC1XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S5PC1XX_SETUP_I2C0) += setup-i2c0.o
obj-$(CONFIG_S5PC1XX_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S5PC1XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
/* linux/arch/arm/plat-s5pc1xx/gpio-config.c
*
* Copyright 2009 Samsung Electronics
*
* S5PC1XX GPIO Configuration.
*
* Based on plat-s3c64xx/gpio-config.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg-s5pc1xx.h>
s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin, unsigned int off)
{
struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
void __iomem *reg;
int shift = off * 2;
u32 drvstr;
if (!chip)
return -EINVAL;
reg = chip->base + 0x0C;
drvstr = __raw_readl(reg);
drvstr = 0xffff & (0x3 << shift);
drvstr = drvstr >> shift;
return (__force s5p_gpio_drvstr_t)drvstr;
}
EXPORT_SYMBOL(s5p_gpio_get_drvstr);
int s5p_gpio_set_drvstr(unsigned int pin, unsigned int off,
s5p_gpio_drvstr_t drvstr)
{
struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
void __iomem *reg;
int shift = off * 2;
u32 tmp;
if (!chip)
return -EINVAL;
reg = chip->base + 0x0C;
tmp = __raw_readl(reg);
tmp |= drvstr << shift;
__raw_writel(tmp, reg);
return 0;
}
EXPORT_SYMBOL(s5p_gpio_set_drvstr);
/* linux/arch/arm/plat-s5pc1xx/include/plat/gpio-cfg.h
*
* Copyright 2009 Samsung Electronic
*
* S5PC1XX 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.
*/
#ifndef __GPIO_CFG_S5PC1XX_H
#define __GPIO_CFG_S5PC1XX_H __FILE__
typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
#define S5P_GPIO_DRVSTR_LV1 0x00
#define S5P_GPIO_DRVSTR_LV2 0x01
#define S5P_GPIO_DRVSTR_LV3 0x10
#define S5P_GPIO_DRVSTR_LV4 0x11
extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin, unsigned int off);
extern int s5p_gpio_set_drvstr(unsigned int pin, unsigned int off,
s5p_gpio_drvstr_t drvstr);
#endif /* __GPIO_CFG_S5PC1XX_H */
......@@ -90,12 +90,6 @@ config S3C_GPIO_CFG_S3C64XX
Internal configuration to enable S3C64XX style GPIO configuration
functions.
config S5P_GPIO_CFG_S5PC1XX
bool
help
Internal configuration to enable S5PC1XX style GPIO configuration
functions.
config S3C_GPIO_PULL_UPDOWN
bool
help
......@@ -111,6 +105,12 @@ config S3C_GPIO_PULL_UP
help
Internal configuration to enable the correct GPIO pull helper
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 0
......@@ -160,6 +160,11 @@ config S3C_DEV_HSMMC2
help
Compile in platform device definitions for HSMMC channel 2
config S3C_DEV_HWMON
bool
help
Compile in platform device definitions for HWMON
config S3C_DEV_I2C1
bool
help
......@@ -185,12 +190,27 @@ config S3C_DEV_NAND
help
Compile in platform device definition for NAND 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 S3C64XX_DEV_SPI
bool
help
Compile in platform device definitions for S3C64XX's type
SPI controllers.
config SAMSUNG_DEV_TS
bool
help
Common in platform device definitions for touchscreen device
# DMA
config S3C_DMA
......@@ -198,6 +218,12 @@ config S3C_DMA
help
Internal configuration for S3C DMA core
config S3C_PL330_DMA
bool
select PL330
help
S3C DMA API Driver for PL330 DMAC.
comment "Power management"
config SAMSUNG_PM_DEBUG
......
......@@ -33,6 +33,7 @@ obj-$(CONFIG_S3C_ADC) += adc.o
obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o
obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmmc1.o
obj-$(CONFIG_S3C_DEV_HSMMC2) += dev-hsmmc2.o
obj-$(CONFIG_S3C_DEV_HWMON) += dev-hwmon.o
obj-y += dev-i2c0.o
obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o
obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o
......@@ -40,11 +41,17 @@ obj-y += dev-uart.o
obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o
obj-$(CONFIG_S3C_DEV_USB_HSOTG) += dev-usb-hsotg.o
obj-$(CONFIG_S3C_DEV_NAND) += dev-nand.o
obj-$(CONFIG_S3C_DEV_RTC) += dev-rtc.o
obj-$(CONFIG_SAMSUNG_DEV_ADC) += dev-adc.o
obj-$(CONFIG_SAMSUNG_DEV_TS) += dev-ts.o
# DMA support
obj-$(CONFIG_S3C_DMA) += dma.o
obj-$(CONFIG_S3C_PL330_DMA) += s3c-pl330.o
# PM support
obj-$(CONFIG_PM) += pm.o
......
/* linux/arch/arm/plat-s3c64xx/dev-adc.c
/* linux/arch/arm/plat-samsung/dev-adc.c
*
* Copyright 2010 Maurus Cuelenaere
*
......@@ -22,8 +22,8 @@
static struct resource s3c_adc_resource[] = {
[0] = {
.start = S3C64XX_PA_ADC,
.end = S3C64XX_PA_ADC + SZ_256 - 1,
.start = SAMSUNG_PA_ADC,
.end = SAMSUNG_PA_ADC + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
......@@ -39,7 +39,7 @@ static struct resource s3c_adc_resource[] = {
};
struct platform_device s3c_device_adc = {
.name = "s3c64xx-adc",
.name = "samsung-adc",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_adc_resource),
.resource = s3c_adc_resource,
......
......@@ -19,7 +19,6 @@
#include <mach/irqs.h>
#include <mach/map.h>
#include <mach/regs-fb.h>
#include <plat/fb.h>
#include <plat/devs.h>
......
/* linux/arch/arm/plat-samsung/dev-hwmon.c
*
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* Adapted for HWMON by Maurus Cuelenaere
*
* Samsung series device definition for HWMON
*
* 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>
#include <plat/hwmon.h>
struct platform_device s3c_device_hwmon = {
.name = "s3c-hwmon",
.id = -1,
.dev.parent = &s3c_device_adc.dev,
};
void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
{
struct s3c_hwmon_pdata *npd;
if (!pd) {
printk(KERN_ERR "%s: no platform data\n", __func__);
return;
}
npd = kmemdup(pd, sizeof(struct s3c_hwmon_pdata), GFP_KERNEL);
if (!npd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
s3c_device_hwmon.dev.platform_data = npd;
}
/* linux/arch/arm/plat-s3c64xx/dev-rtc.c
/* linux/arch/arm/plat-samsung/dev-rtc.c
*
* Copyright 2009 by Maurus Cuelenaere <mcuelenaere@gmail.com>
*
......@@ -18,26 +18,26 @@
static struct resource s3c_rtc_resource[] = {
[0] = {
.start = S3C64XX_PA_RTC,
.end = S3C64XX_PA_RTC + 0xff,
.flags = IORESOURCE_MEM,
.start = S3C_PA_RTC,
.end = S3C_PA_RTC + 0xff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_RTC_ALARM,
.end = IRQ_RTC_ALARM,
.flags = IORESOURCE_IRQ,
.start = IRQ_RTC_ALARM,
.end = IRQ_RTC_ALARM,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = IRQ_RTC_TIC,
.end = IRQ_RTC_TIC,
.flags = IORESOURCE_IRQ
.start = IRQ_RTC_TIC,
.end = IRQ_RTC_TIC,
.flags = IORESOURCE_IRQ
}
};
struct platform_device s3c_device_rtc = {
.name = "s3c64xx-rtc",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_rtc_resource),
.resource = s3c_rtc_resource,
.name = "s3c64xx-rtc",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_rtc_resource),
.resource = s3c_rtc_resource,
};
EXPORT_SYMBOL(s3c_device_rtc);
/* linux/arch/arm/mach-s3c64xx/dev-ts.c
*
* Copyright (c) 2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
*
* Adapted by Maurus Cuelenaere for s3c64xx
*
* S3C64XX series device definition for touchscreen device
*
* 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/string.h>
#include <linux/platform_device.h>
#include <mach/irqs.h>
#include <mach/map.h>
#include <plat/devs.h>
#include <plat/ts.h>
static struct resource s3c_ts_resource[] = {
[0] = {
.start = SAMSUNG_PA_ADC,
.end = SAMSUNG_PA_ADC + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_TC,
.end = IRQ_TC,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device s3c_device_ts = {
.name = "s3c64xx-ts",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_ts_resource),
.resource = s3c_ts_resource,
};
void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
{
struct s3c2410_ts_mach_info *npd;
if (!pd) {
printk(KERN_ERR "%s: no platform data\n", __func__);
return;
}
npd = kmemdup(pd, sizeof(struct s3c2410_ts_mach_info), GFP_KERNEL);
if (!npd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
s3c_device_ts.dev.platform_data = npd;
}
EXPORT_SYMBOL(s3c24xx_ts_set_platdata);
......@@ -33,9 +33,9 @@ int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
offset = pin - chip->chip.base;
local_irq_save(flags);
s3c_gpio_lock(chip, flags);
ret = s3c_gpio_do_setcfg(chip, offset, config);
local_irq_restore(flags);
s3c_gpio_unlock(chip, flags);
return ret;
}
......@@ -51,9 +51,9 @@ unsigned s3c_gpio_getcfg(unsigned int pin)
if (chip) {
offset = pin - chip->chip.base;
local_irq_save(flags);
s3c_gpio_lock(chip, flags);
ret = s3c_gpio_do_getcfg(chip, offset);
local_irq_restore(flags);
s3c_gpio_unlock(chip, flags);
}
return ret;
......@@ -72,9 +72,9 @@ int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
offset = pin - chip->chip.base;
local_irq_save(flags);
s3c_gpio_lock(chip, flags);
ret = s3c_gpio_do_setpull(chip, offset, pull);
local_irq_restore(flags);
s3c_gpio_unlock(chip, flags);
return ret;
}
......@@ -261,3 +261,51 @@ s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
}
#endif /* CONFIG_S3C_GPIO_PULL_UP */
#ifdef CONFIG_S5P_GPIO_DRVSTR
s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
{
struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
unsigned int off;
void __iomem *reg;
int shift;
u32 drvstr;
if (!chip)
return -EINVAL;
off = chip->chip.base - pin;
shift = off * 2;
reg = chip->base + 0x0C;
drvstr = __raw_readl(reg);
drvstr = 0xffff & (0x3 << shift);
drvstr = drvstr >> shift;
return (__force s5p_gpio_drvstr_t)drvstr;
}
EXPORT_SYMBOL(s5p_gpio_get_drvstr);
int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
{
struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
unsigned int off;
void __iomem *reg;
int shift;
u32 tmp;
if (!chip)
return -EINVAL;
off = chip->chip.base - pin;
shift = off * 2;
reg = chip->base + 0x0C;
tmp = __raw_readl(reg);
tmp |= drvstr << shift;
__raw_writel(tmp, reg);
return 0;
}
EXPORT_SYMBOL(s5p_gpio_set_drvstr);
#endif /* CONFIG_S5P_GPIO_DRVSTR */
......@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/spinlock.h>
#include <plat/gpio-core.h>
......@@ -52,14 +53,14 @@ static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
unsigned long flags;
unsigned long con;
local_irq_save(flags);
s3c_gpio_lock(ourchip, flags);
con = __raw_readl(base + 0x00);
con &= ~(3 << (offset * 2));
__raw_writel(con, base + 0x00);
local_irq_restore(flags);
s3c_gpio_unlock(ourchip, flags);
return 0;
}
......@@ -72,7 +73,7 @@ static int s3c_gpiolib_output(struct gpio_chip *chip,
unsigned long dat;
unsigned long con;
local_irq_save(flags);
s3c_gpio_lock(ourchip, flags);
dat = __raw_readl(base + 0x04);
dat &= ~(1 << offset);
......@@ -87,7 +88,7 @@ static int s3c_gpiolib_output(struct gpio_chip *chip,
__raw_writel(con, base + 0x00);
__raw_writel(dat, base + 0x04);
local_irq_restore(flags);
s3c_gpio_unlock(ourchip, flags);
return 0;
}
......@@ -99,7 +100,7 @@ static void s3c_gpiolib_set(struct gpio_chip *chip,
unsigned long flags;
unsigned long dat;
local_irq_save(flags);
s3c_gpio_lock(ourchip, flags);
dat = __raw_readl(base + 0x04);
dat &= ~(1 << offset);
......@@ -107,7 +108,7 @@ static void s3c_gpiolib_set(struct gpio_chip *chip,
dat |= 1 << offset;
__raw_writel(dat, base + 0x04);
local_irq_restore(flags);
s3c_gpio_unlock(ourchip, flags);
}
static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
......@@ -131,6 +132,8 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
BUG_ON(!gc->label);
BUG_ON(!gc->ngpio);
spin_lock_init(&chip->lock);
if (!gc->direction_input)
gc->direction_input = s3c_gpiolib_input;
if (!gc->direction_output)
......
......@@ -74,6 +74,7 @@ extern struct clk clk_ext;
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;
......
......@@ -79,6 +79,9 @@ extern struct sysdev_class s3c2442_sysclass;
extern struct sysdev_class s3c2443_sysclass;
extern struct sysdev_class s3c6410_sysclass;
extern struct sysdev_class s3c64xx_sysclass;
extern struct sysdev_class s5p6440_sysclass;
extern struct sysdev_class s5p6442_sysclass;
extern struct sysdev_class s5pv210_sysclass;
extern void (*s5pc1xx_idle)(void);
......
......@@ -64,6 +64,22 @@ extern struct platform_device s3c_device_nand;
extern struct platform_device s3c_device_usbgadget;
extern struct platform_device s3c_device_usb_hsotg;
extern struct platform_device s5pv210_device_ac97;
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_iis0;
extern struct platform_device s5pv210_device_iis1;
extern struct platform_device s5pv210_device_iis2;
extern struct platform_device s5p6442_device_pcm0;
extern struct platform_device s5p6442_device_pcm1;
extern struct platform_device s5p6442_device_iis0;
extern struct platform_device s5p6442_device_iis1;
extern struct platform_device s5p6440_device_pcm;
extern struct platform_device s5p6440_device_iis;
/* s3c2440 specific devices */
#ifdef CONFIG_CPU_S3C2440
......
......@@ -110,8 +110,8 @@ extern int s3c2410_dma_config(unsigned int channel, int xferunit);
* configure the device we're talking to
*/
extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
unsigned long devaddr);
extern int s3c2410_dma_devconfig(unsigned int channel,
enum s3c2410_dmasrc source, unsigned long devaddr);
/* s3c2410_dma_getposition
*
......
......@@ -15,6 +15,13 @@
#ifndef __PLAT_S3C_FB_H
#define __PLAT_S3C_FB_H __FILE__
/* S3C_FB_MAX_WIN
* Set to the maximum number of windows that any of the supported hardware
* can use. Since the platform data uses this for an array size, having it
* set to the maximum of any version of the hardware can do is safe.
*/
#define S3C_FB_MAX_WIN (5)
/**
* struct s3c_fb_pd_win - per window setup data
* @win_mode: The display parameters to initialise (not for window 0)
......
......@@ -25,6 +25,7 @@
#define __PLAT_GPIO_CFG_H __FILE__
typedef unsigned int __bitwise__ s3c_gpio_pull_t;
typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
/* forward declaration if gpio-core.h hasn't been included */
struct s3c_gpio_chip;
......@@ -118,4 +119,33 @@ extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
*/
extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
/* 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 S5C series.
*/
#define S5P_GPIO_DRVSTR_LV1 ((__force s5p_gpio_drvstr_t)0x00)
#define S5P_GPIO_DRVSTR_LV2 ((__force s5p_gpio_drvstr_t)0x01)
#define S5P_GPIO_DRVSTR_LV3 ((__force s5p_gpio_drvstr_t)0x10)
#define S5P_GPIO_DRVSTR_LV4 ((__force s5p_gpio_drvstr_t)0x11)
/**
* 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 successfull, 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);
#endif /* __PLAT_GPIO_CFG_H */
......@@ -44,16 +44,26 @@ struct s3c_gpio_cfg;
* @chip: The chip structure to be exported via gpiolib.
* @base: The base pointer to the gpio configuration registers.
* @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.
*
* 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 s3c_gpio_chip {
struct gpio_chip chip;
struct s3c_gpio_cfg *config;
struct s3c_gpio_pm *pm;
void __iomem *base;
spinlock_t lock;
#ifdef CONFIG_PM
u32 pm_save[4];
#endif
......@@ -138,3 +148,7 @@ extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
#define __gpio_pm(x) NULL
#endif /* CONFIG_PM */
/* locking wrappers to deal with multiple access to the same gpio bank */
#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
#define s3c_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
......@@ -37,5 +37,15 @@ struct s3c_hwmon_pdata {
struct s3c_hwmon_chcfg *in[8];
};
/**
* s3c_hwmon_set_platdata - Set platform data for S3C HWMON device
* @pd: Platform data to register to device.
*
* Register the given platform data for use with the S3C HWMON device.
* The call will copy the platform data, so the board definitions can
* make the structure itself __initdata.
*/
extern void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd);
#endif /* __ASM_ARCH_ADC_HWMON_H */
/*
* 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 __S3C_DMA_PL330_H_
#define __S3C_DMA_PL330_H_
#define S3C2410_DMAF_AUTOSTART (1 << 0)
#define S3C2410_DMAF_CIRCULAR (1 << 1)
/*
* 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 S3C PL330 API driver
* use these just as IDs.
*/
enum dma_ch {
DMACH_UART0_RX,
DMACH_UART0_TX,
DMACH_UART1_RX,
DMACH_UART1_TX,
DMACH_UART2_RX,
DMACH_UART2_TX,
DMACH_UART3_RX,
DMACH_UART3_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,
/* END Marker, also used to denote a reserved channel */
DMACH_MAX,
};
static inline bool s3c_dma_has_circular(void)
{
return true;
}
#include <plat/dma.h>
#endif /* __S3C_DMA_PL330_H_ */
/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
*
* 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 __S3C_PL330_PDATA_H
#define __S3C_PL330_PDATA_H
#include <plat/s3c-dma-pl330.h>
/*
* Every PL330 DMAC has max 32 peripheral interfaces,
* of which some may be not be really used in your
* DMAC's configuration.
* Populate this array of 32 peri i/fs with relevant
* channel IDs for used peri i/f and DMACH_MAX for
* those unused.
*
* The platforms just need to provide this info
* to the S3C DMA API driver for PL330.
*/
struct s3c_pl330_platdata {
enum dma_ch peri[32];
};
#endif /* __S3C_PL330_PDATA_H */
/* linux/include/asm/arch-s3c2410/ts.h
/* arch/arm/plat-samsung/include/plat/ts.h
*
* Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
*
......@@ -14,8 +14,12 @@ struct s3c2410_ts_mach_info {
int delay;
int presc;
int oversampling_shift;
void (*cfg_gpio)(struct platform_device *dev);
};
extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *);
/* defined by architecture to configure gpio */
extern void s3c24xx_ts_cfg_gpio(struct platform_device *dev);
#endif /* __ASM_ARM_TS_H */
......@@ -329,7 +329,7 @@ void s3c_pm_save_gpios(void)
struct s3c_gpio_chip *ourchip;
unsigned int gpio_nr;
for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
ourchip = s3c_gpiolib_getchip(gpio_nr);
if (!ourchip)
continue;
......@@ -367,7 +367,7 @@ void s3c_pm_restore_gpios(void)
struct s3c_gpio_chip *ourchip;
unsigned int gpio_nr;
for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
ourchip = s3c_gpiolib_getchip(gpio_nr);
if (!ourchip)
continue;
......
/* linux/arch/arm/plat-samsung/s3c-pl330.c
*
* 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.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <asm/hardware/pl330.h>
#include <plat/s3c-pl330-pdata.h>
/**
* struct s3c_pl330_dmac - Logical representation of a PL330 DMAC.
* @busy_chan: Number of channels currently busy.
* @peri: List of IDs of peripherals this DMAC can work with.
* @node: To attach to the global list of DMACs.
* @pi: PL330 configuration info for the DMAC.
* @kmcache: Pool to quickly allocate xfers for all channels in the dmac.
*/
struct s3c_pl330_dmac {
unsigned busy_chan;
enum dma_ch *peri;
struct list_head node;
struct pl330_info *pi;
struct kmem_cache *kmcache;
};
/**
* struct s3c_pl330_xfer - A request submitted by S3C DMA clients.
* @token: Xfer ID provided by the client.
* @node: To attach to the list of xfers on a channel.
* @px: Xfer for PL330 core.
* @chan: Owner channel of this xfer.
*/
struct s3c_pl330_xfer {
void *token;
struct list_head node;
struct pl330_xfer px;
struct s3c_pl330_chan *chan;
};
/**
* struct s3c_pl330_chan - Logical channel to communicate with
* a Physical peripheral.
* @pl330_chan_id: Token of a hardware channel thread of PL330 DMAC.
* NULL if the channel is available to be acquired.
* @id: ID of the peripheral that this channel can communicate with.
* @options: Options specified by the client.
* @sdaddr: Address provided via s3c2410_dma_devconfig.
* @node: To attach to the global list of channels.
* @lrq: Pointer to the last submitted pl330_req to PL330 core.
* @xfer_list: To manage list of xfers enqueued.
* @req: Two requests to communicate with the PL330 engine.
* @callback_fn: Callback function to the client.
* @rqcfg: Channel configuration for the xfers.
* @xfer_head: Pointer to the xfer to be next excecuted.
* @dmac: Pointer to the DMAC that manages this channel, NULL if the
* channel is available to be acquired.
* @client: Client of this channel. NULL if the
* channel is available to be acquired.
*/
struct s3c_pl330_chan {
void *pl330_chan_id;
enum dma_ch id;
unsigned int options;
unsigned long sdaddr;
struct list_head node;
struct pl330_req *lrq;
struct list_head xfer_list;
struct pl330_req req[2];
s3c2410_dma_cbfn_t callback_fn;
struct pl330_reqcfg rqcfg;
struct s3c_pl330_xfer *xfer_head;
struct s3c_pl330_dmac *dmac;
struct s3c2410_dma_client *client;
};
/* All DMACs in the platform */
static LIST_HEAD(dmac_list);
/* All channels to peripherals in the platform */
static LIST_HEAD(chan_list);
/*
* Since we add resources(DMACs and Channels) to the global pool,
* we need to guard access to the resources using a global lock
*/
static DEFINE_SPINLOCK(res_lock);
/* Returns the channel with ID 'id' in the chan_list */
static struct s3c_pl330_chan *id_to_chan(const enum dma_ch id)
{
struct s3c_pl330_chan *ch;
list_for_each_entry(ch, &chan_list, node)
if (ch->id == id)
return ch;
return NULL;
}
/* Allocate a new channel with ID 'id' and add to chan_list */
static void chan_add(const enum dma_ch id)
{
struct s3c_pl330_chan *ch = id_to_chan(id);
/* Return if the channel already exists */
if (ch)
return;
ch = kmalloc(sizeof(*ch), GFP_KERNEL);
/* Return silently to work with other channels */
if (!ch)
return;
ch->id = id;
ch->dmac = NULL;
list_add_tail(&ch->node, &chan_list);
}
/* If the channel is not yet acquired by any client */
static bool chan_free(struct s3c_pl330_chan *ch)
{
if (!ch)
return false;
/* Channel points to some DMAC only when it's acquired */
return ch->dmac ? false : true;
}
/*
* Returns 0 is peripheral i/f is invalid or not present on the dmac.
* Index + 1, otherwise.
*/
static unsigned iface_of_dmac(struct s3c_pl330_dmac *dmac, enum dma_ch ch_id)
{
enum dma_ch *id = dmac->peri;
int i;
/* Discount invalid markers */
if (ch_id == DMACH_MAX)
return 0;
for (i = 0; i < PL330_MAX_PERI; i++)
if (id[i] == ch_id)
return i + 1;
return 0;
}
/* If all channel threads of the DMAC are busy */
static inline bool dmac_busy(struct s3c_pl330_dmac *dmac)
{
struct pl330_info *pi = dmac->pi;
return (dmac->busy_chan < pi->pcfg.num_chan) ? false : true;
}
/*
* Returns the number of free channels that
* can be handled by this dmac only.
*/
static unsigned ch_onlyby_dmac(struct s3c_pl330_dmac *dmac)
{
enum dma_ch *id = dmac->peri;
struct s3c_pl330_dmac *d;
struct s3c_pl330_chan *ch;
unsigned found, count = 0;
enum dma_ch p;
int i;
for (i = 0; i < PL330_MAX_PERI; i++) {
p = id[i];
ch = id_to_chan(p);
if (p == DMACH_MAX || !chan_free(ch))
continue;
found = 0;
list_for_each_entry(d, &dmac_list, node) {
if (d != dmac && iface_of_dmac(d, ch->id)) {
found = 1;
break;
}
}
if (!found)
count++;
}
return count;
}
/*
* Measure of suitability of 'dmac' handling 'ch'
*
* 0 indicates 'dmac' can not handle 'ch' either
* because it is not supported by the hardware or
* because all dmac channels are currently busy.
*
* >0 vlaue indicates 'dmac' has the capability.
* The bigger the value the more suitable the dmac.
*/
#define MAX_SUIT UINT_MAX
#define MIN_SUIT 0
static unsigned suitablility(struct s3c_pl330_dmac *dmac,
struct s3c_pl330_chan *ch)
{
struct pl330_info *pi = dmac->pi;
enum dma_ch *id = dmac->peri;
struct s3c_pl330_dmac *d;
unsigned s;
int i;
s = MIN_SUIT;
/* If all the DMAC channel threads are busy */
if (dmac_busy(dmac))
return s;
for (i = 0; i < PL330_MAX_PERI; i++)
if (id[i] == ch->id)
break;
/* If the 'dmac' can't talk to 'ch' */
if (i == PL330_MAX_PERI)
return s;
s = MAX_SUIT;
list_for_each_entry(d, &dmac_list, node) {
/*
* If some other dmac can talk to this
* peri and has some channel free.
*/
if (d != dmac && iface_of_dmac(d, ch->id) && !dmac_busy(d)) {
s = 0;
break;
}
}
if (s)
return s;
s = 100;
/* Good if free chans are more, bad otherwise */
s += (pi->pcfg.num_chan - dmac->busy_chan) - ch_onlyby_dmac(dmac);
return s;
}
/* More than one DMAC may have capability to transfer data with the
* peripheral. This function assigns most suitable DMAC to manage the
* channel and hence communicate with the peripheral.
*/
static struct s3c_pl330_dmac *map_chan_to_dmac(struct s3c_pl330_chan *ch)
{
struct s3c_pl330_dmac *d, *dmac = NULL;
unsigned sn, sl = MIN_SUIT;
list_for_each_entry(d, &dmac_list, node) {
sn = suitablility(d, ch);
if (sn == MAX_SUIT)
return d;
if (sn > sl)
dmac = d;
}
return dmac;
}
/* Acquire the channel for peripheral 'id' */
static struct s3c_pl330_chan *chan_acquire(const enum dma_ch id)
{
struct s3c_pl330_chan *ch = id_to_chan(id);
struct s3c_pl330_dmac *dmac;
/* If the channel doesn't exist or is already acquired */
if (!ch || !chan_free(ch)) {
ch = NULL;
goto acq_exit;
}
dmac = map_chan_to_dmac(ch);
/* If couldn't map */
if (!dmac) {
ch = NULL;
goto acq_exit;
}
dmac->busy_chan++;
ch->dmac = dmac;
acq_exit:
return ch;
}
/* Delete xfer from the queue */
static inline void del_from_queue(struct s3c_pl330_xfer *xfer)
{
struct s3c_pl330_xfer *t;
struct s3c_pl330_chan *ch;
int found;
if (!xfer)
return;
ch = xfer->chan;
/* Make sure xfer is in the queue */
found = 0;
list_for_each_entry(t, &ch->xfer_list, node)
if (t == xfer) {
found = 1;
break;
}
if (!found)
return;
/* If xfer is last entry in the queue */
if (xfer->node.next == &ch->xfer_list)
t = list_entry(ch->xfer_list.next,
struct s3c_pl330_xfer, node);
else
t = list_entry(xfer->node.next,
struct s3c_pl330_xfer, node);
/* If there was only one node left */
if (t == xfer)
ch->xfer_head = NULL;
else if (ch->xfer_head == xfer)
ch->xfer_head = t;
list_del(&xfer->node);
}
/* Provides pointer to the next xfer in the queue.
* If CIRCULAR option is set, the list is left intact,
* otherwise the xfer is removed from the list.
* Forced delete 'pluck' can be set to override the CIRCULAR option.
*/
static struct s3c_pl330_xfer *get_from_queue(struct s3c_pl330_chan *ch,
int pluck)
{
struct s3c_pl330_xfer *xfer = ch->xfer_head;
if (!xfer)
return NULL;
/* If xfer is last entry in the queue */
if (xfer->node.next == &ch->xfer_list)
ch->xfer_head = list_entry(ch->xfer_list.next,
struct s3c_pl330_xfer, node);
else
ch->xfer_head = list_entry(xfer->node.next,
struct s3c_pl330_xfer, node);
if (pluck || !(ch->options & S3C2410_DMAF_CIRCULAR))
del_from_queue(xfer);
return xfer;
}
static inline void add_to_queue(struct s3c_pl330_chan *ch,
struct s3c_pl330_xfer *xfer, int front)
{
struct pl330_xfer *xt;
/* If queue empty */
if (ch->xfer_head == NULL)
ch->xfer_head = xfer;
xt = &ch->xfer_head->px;
/* If the head already submitted (CIRCULAR head) */
if (ch->options & S3C2410_DMAF_CIRCULAR &&
(xt == ch->req[0].x || xt == ch->req[1].x))
ch->xfer_head = xfer;
/* If this is a resubmission, it should go at the head */
if (front) {
ch->xfer_head = xfer;
list_add(&xfer->node, &ch->xfer_list);
} else {
list_add_tail(&xfer->node, &ch->xfer_list);
}
}
static inline void _finish_off(struct s3c_pl330_xfer *xfer,
enum s3c2410_dma_buffresult res, int ffree)
{
struct s3c_pl330_chan *ch;
if (!xfer)
return;
ch = xfer->chan;
/* Do callback */
if (ch->callback_fn)
ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res);
/* Force Free or if buffer is not needed anymore */
if (ffree || !(ch->options & S3C2410_DMAF_CIRCULAR))
kmem_cache_free(ch->dmac->kmcache, xfer);
}
static inline int s3c_pl330_submit(struct s3c_pl330_chan *ch,
struct pl330_req *r)
{
struct s3c_pl330_xfer *xfer;
int ret = 0;
/* If already submitted */
if (r->x)
return 0;
xfer = get_from_queue(ch, 0);
if (xfer) {
r->x = &xfer->px;
/* Use max bandwidth for M<->M xfers */
if (r->rqtype == MEMTOMEM) {
struct pl330_info *pi = xfer->chan->dmac->pi;
int burst = 1 << ch->rqcfg.brst_size;
u32 bytes = r->x->bytes;
int bl;
bl = pi->pcfg.data_bus_width / 8;
bl *= pi->pcfg.data_buf_dep;
bl /= burst;
/* src/dst_burst_len can't be more than 16 */
if (bl > 16)
bl = 16;
while (bl > 1) {
if (!(bytes % (bl * burst)))
break;
bl--;
}
ch->rqcfg.brst_len = bl;
} else {
ch->rqcfg.brst_len = 1;
}
ret = pl330_submit_req(ch->pl330_chan_id, r);
/* If submission was successful */
if (!ret) {
ch->lrq = r; /* latest submitted req */
return 0;
}
r->x = NULL;
/* If both of the PL330 ping-pong buffers filled */
if (ret == -EAGAIN) {
dev_err(ch->dmac->pi->dev, "%s:%d!\n",
__func__, __LINE__);
/* Queue back again */
add_to_queue(ch, xfer, 1);
ret = 0;
} else {
dev_err(ch->dmac->pi->dev, "%s:%d!\n",
__func__, __LINE__);
_finish_off(xfer, S3C2410_RES_ERR, 0);
}
}
return ret;
}
static void s3c_pl330_rq(struct s3c_pl330_chan *ch,
struct pl330_req *r, enum pl330_op_err err)
{
unsigned long flags;
struct s3c_pl330_xfer *xfer;
struct pl330_xfer *xl = r->x;
enum s3c2410_dma_buffresult res;
spin_lock_irqsave(&res_lock, flags);
r->x = NULL;
s3c_pl330_submit(ch, r);
spin_unlock_irqrestore(&res_lock, flags);
/* Map result to S3C DMA API */
if (err == PL330_ERR_NONE)
res = S3C2410_RES_OK;
else if (err == PL330_ERR_ABORT)
res = S3C2410_RES_ABORT;
else
res = S3C2410_RES_ERR;
/* If last request had some xfer */
if (xl) {
xfer = container_of(xl, struct s3c_pl330_xfer, px);
_finish_off(xfer, res, 0);
} else {
dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n",
__func__, __LINE__);
}
}
static void s3c_pl330_rq0(void *token, enum pl330_op_err err)
{
struct pl330_req *r = token;
struct s3c_pl330_chan *ch = container_of(r,
struct s3c_pl330_chan, req[0]);
s3c_pl330_rq(ch, r, err);
}
static void s3c_pl330_rq1(void *token, enum pl330_op_err err)
{
struct pl330_req *r = token;
struct s3c_pl330_chan *ch = container_of(r,
struct s3c_pl330_chan, req[1]);
s3c_pl330_rq(ch, r, err);
}
/* Release an acquired channel */
static void chan_release(struct s3c_pl330_chan *ch)
{
struct s3c_pl330_dmac *dmac;
if (chan_free(ch))
return;
dmac = ch->dmac;
ch->dmac = NULL;
dmac->busy_chan--;
}
int s3c2410_dma_ctrl(enum dma_ch id, enum s3c2410_chan_op op)
{
struct s3c_pl330_xfer *xfer;
enum pl330_chan_op pl330op;
struct s3c_pl330_chan *ch;
unsigned long flags;
int idx, ret;
spin_lock_irqsave(&res_lock, flags);
ch = id_to_chan(id);
if (!ch || chan_free(ch)) {
ret = -EINVAL;
goto ctrl_exit;
}
switch (op) {
case S3C2410_DMAOP_START:
/* Make sure both reqs are enqueued */
idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
s3c_pl330_submit(ch, &ch->req[idx]);
s3c_pl330_submit(ch, &ch->req[1 - idx]);
pl330op = PL330_OP_START;
break;
case S3C2410_DMAOP_STOP:
pl330op = PL330_OP_ABORT;
break;
case S3C2410_DMAOP_FLUSH:
pl330op = PL330_OP_FLUSH;
break;
case S3C2410_DMAOP_PAUSE:
case S3C2410_DMAOP_RESUME:
case S3C2410_DMAOP_TIMEOUT:
case S3C2410_DMAOP_STARTED:
spin_unlock_irqrestore(&res_lock, flags);
return 0;
default:
spin_unlock_irqrestore(&res_lock, flags);
return -EINVAL;
}
ret = pl330_chan_ctrl(ch->pl330_chan_id, pl330op);
if (pl330op == PL330_OP_START) {
spin_unlock_irqrestore(&res_lock, flags);
return ret;
}
idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
/* Abort the current xfer */
if (ch->req[idx].x) {
xfer = container_of(ch->req[idx].x,
struct s3c_pl330_xfer, px);
/* Drop xfer during FLUSH */
if (pl330op == PL330_OP_FLUSH)
del_from_queue(xfer);
ch->req[idx].x = NULL;
spin_unlock_irqrestore(&res_lock, flags);
_finish_off(xfer, S3C2410_RES_ABORT,
pl330op == PL330_OP_FLUSH ? 1 : 0);
spin_lock_irqsave(&res_lock, flags);
}
/* Flush the whole queue */
if (pl330op == PL330_OP_FLUSH) {
if (ch->req[1 - idx].x) {
xfer = container_of(ch->req[1 - idx].x,
struct s3c_pl330_xfer, px);
del_from_queue(xfer);
ch->req[1 - idx].x = NULL;
spin_unlock_irqrestore(&res_lock, flags);
_finish_off(xfer, S3C2410_RES_ABORT, 1);
spin_lock_irqsave(&res_lock, flags);
}
/* Finish off the remaining in the queue */
xfer = ch->xfer_head;
while (xfer) {
del_from_queue(xfer);
spin_unlock_irqrestore(&res_lock, flags);
_finish_off(xfer, S3C2410_RES_ABORT, 1);
spin_lock_irqsave(&res_lock, flags);
xfer = ch->xfer_head;
}
}
ctrl_exit:
spin_unlock_irqrestore(&res_lock, flags);
return ret;
}
EXPORT_SYMBOL(s3c2410_dma_ctrl);
int s3c2410_dma_enqueue(enum dma_ch id, void *token,
dma_addr_t addr, int size)
{
struct s3c_pl330_chan *ch;
struct s3c_pl330_xfer *xfer;
unsigned long flags;
int idx, ret = 0;
spin_lock_irqsave(&res_lock, flags);
ch = id_to_chan(id);
/* Error if invalid or free channel */
if (!ch || chan_free(ch)) {
ret = -EINVAL;
goto enq_exit;
}
/* Error if size is unaligned */
if (ch->rqcfg.brst_size && size % (1 << ch->rqcfg.brst_size)) {
ret = -EINVAL;
goto enq_exit;
}
xfer = kmem_cache_alloc(ch->dmac->kmcache, GFP_ATOMIC);
if (!xfer) {
ret = -ENOMEM;
goto enq_exit;
}
xfer->token = token;
xfer->chan = ch;
xfer->px.bytes = size;
xfer->px.next = NULL; /* Single request */
/* For S3C DMA API, direction is always fixed for all xfers */
if (ch->req[0].rqtype == MEMTODEV) {
xfer->px.src_addr = addr;
xfer->px.dst_addr = ch->sdaddr;
} else {
xfer->px.src_addr = ch->sdaddr;
xfer->px.dst_addr = addr;
}
add_to_queue(ch, xfer, 0);
/* Try submitting on either request */
idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
if (!ch->req[idx].x)
s3c_pl330_submit(ch, &ch->req[idx]);
else
s3c_pl330_submit(ch, &ch->req[1 - idx]);
spin_unlock_irqrestore(&res_lock, flags);
if (ch->options & S3C2410_DMAF_AUTOSTART)
s3c2410_dma_ctrl(id, S3C2410_DMAOP_START);
return 0;
enq_exit:
spin_unlock_irqrestore(&res_lock, flags);
return ret;
}
EXPORT_SYMBOL(s3c2410_dma_enqueue);
int s3c2410_dma_request(enum dma_ch id,
struct s3c2410_dma_client *client,
void *dev)
{
struct s3c_pl330_dmac *dmac;
struct s3c_pl330_chan *ch;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&res_lock, flags);
ch = chan_acquire(id);
if (!ch) {
ret = -EBUSY;
goto req_exit;
}
dmac = ch->dmac;
ch->pl330_chan_id = pl330_request_channel(dmac->pi);
if (!ch->pl330_chan_id) {
chan_release(ch);
ret = -EBUSY;
goto req_exit;
}
ch->client = client;
ch->options = 0; /* Clear any option */
ch->callback_fn = NULL; /* Clear any callback */
ch->lrq = NULL;
ch->rqcfg.brst_size = 2; /* Default word size */
ch->rqcfg.swap = SWAP_NO;
ch->rqcfg.scctl = SCCTRL0; /* Noncacheable and nonbufferable */
ch->rqcfg.dcctl = DCCTRL0; /* Noncacheable and nonbufferable */
ch->rqcfg.privileged = 0;
ch->rqcfg.insnaccess = 0;
/* Set invalid direction */
ch->req[0].rqtype = DEVTODEV;
ch->req[1].rqtype = ch->req[0].rqtype;
ch->req[0].cfg = &ch->rqcfg;
ch->req[1].cfg = ch->req[0].cfg;
ch->req[0].peri = iface_of_dmac(dmac, id) - 1; /* Original index */
ch->req[1].peri = ch->req[0].peri;
ch->req[0].token = &ch->req[0];
ch->req[0].xfer_cb = s3c_pl330_rq0;
ch->req[1].token = &ch->req[1];
ch->req[1].xfer_cb = s3c_pl330_rq1;
ch->req[0].x = NULL;
ch->req[1].x = NULL;
/* Reset xfer list */
INIT_LIST_HEAD(&ch->xfer_list);
ch->xfer_head = NULL;
req_exit:
spin_unlock_irqrestore(&res_lock, flags);
return ret;
}
EXPORT_SYMBOL(s3c2410_dma_request);
int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client)
{
struct s3c_pl330_chan *ch;
struct s3c_pl330_xfer *xfer;
unsigned long flags;
int ret = 0;
unsigned idx;
spin_lock_irqsave(&res_lock, flags);
ch = id_to_chan(id);
if (!ch || chan_free(ch))
goto free_exit;
/* Refuse if someone else wanted to free the channel */
if (ch->client != client) {
ret = -EBUSY;
goto free_exit;
}
/* Stop any active xfer, Flushe the queue and do callbacks */
pl330_chan_ctrl(ch->pl330_chan_id, PL330_OP_FLUSH);
/* Abort the submitted requests */
idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
if (ch->req[idx].x) {
xfer = container_of(ch->req[idx].x,
struct s3c_pl330_xfer, px);
ch->req[idx].x = NULL;
del_from_queue(xfer);
spin_unlock_irqrestore(&res_lock, flags);
_finish_off(xfer, S3C2410_RES_ABORT, 1);
spin_lock_irqsave(&res_lock, flags);
}
if (ch->req[1 - idx].x) {
xfer = container_of(ch->req[1 - idx].x,
struct s3c_pl330_xfer, px);
ch->req[1 - idx].x = NULL;
del_from_queue(xfer);
spin_unlock_irqrestore(&res_lock, flags);
_finish_off(xfer, S3C2410_RES_ABORT, 1);
spin_lock_irqsave(&res_lock, flags);
}
/* Pluck and Abort the queued requests in order */
do {
xfer = get_from_queue(ch, 1);
spin_unlock_irqrestore(&res_lock, flags);
_finish_off(xfer, S3C2410_RES_ABORT, 1);
spin_lock_irqsave(&res_lock, flags);
} while (xfer);
ch->client = NULL;
pl330_release_channel(ch->pl330_chan_id);
ch->pl330_chan_id = NULL;
chan_release(ch);
free_exit:
spin_unlock_irqrestore(&res_lock, flags);
return ret;
}
EXPORT_SYMBOL(s3c2410_dma_free);
int s3c2410_dma_config(enum dma_ch id, int xferunit)
{
struct s3c_pl330_chan *ch;
struct pl330_info *pi;
unsigned long flags;
int i, dbwidth, ret = 0;
spin_lock_irqsave(&res_lock, flags);
ch = id_to_chan(id);
if (!ch || chan_free(ch)) {
ret = -EINVAL;
goto cfg_exit;
}
pi = ch->dmac->pi;
dbwidth = pi->pcfg.data_bus_width / 8;
/* Max size of xfer can be pcfg.data_bus_width */
if (xferunit > dbwidth) {
ret = -EINVAL;
goto cfg_exit;
}
i = 0;
while (xferunit != (1 << i))
i++;
/* If valid value */
if (xferunit == (1 << i))
ch->rqcfg.brst_size = i;
else
ret = -EINVAL;
cfg_exit:
spin_unlock_irqrestore(&res_lock, flags);
return ret;
}
EXPORT_SYMBOL(s3c2410_dma_config);
/* Options that are supported by this driver */
#define S3C_PL330_FLAGS (S3C2410_DMAF_CIRCULAR | S3C2410_DMAF_AUTOSTART)
int s3c2410_dma_setflags(enum dma_ch id, unsigned int options)
{
struct s3c_pl330_chan *ch;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&res_lock, flags);
ch = id_to_chan(id);
if (!ch || chan_free(ch) || options & ~(S3C_PL330_FLAGS))
ret = -EINVAL;
else
ch->options = options;
spin_unlock_irqrestore(&res_lock, flags);
return 0;
}
EXPORT_SYMBOL(s3c2410_dma_setflags);
int s3c2410_dma_set_buffdone_fn(enum dma_ch id, s3c2410_dma_cbfn_t rtn)
{
struct s3c_pl330_chan *ch;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&res_lock, flags);
ch = id_to_chan(id);
if (!ch || chan_free(ch))
ret = -EINVAL;
else
ch->callback_fn = rtn;
spin_unlock_irqrestore(&res_lock, flags);
return ret;
}
EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source,
unsigned long address)
{
struct s3c_pl330_chan *ch;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&res_lock, flags);
ch = id_to_chan(id);
if (!ch || chan_free(ch)) {
ret = -EINVAL;
goto devcfg_exit;
}
switch (source) {
case S3C2410_DMASRC_HW: /* P->M */
ch->req[0].rqtype = DEVTOMEM;
ch->req[1].rqtype = DEVTOMEM;
ch->rqcfg.src_inc = 0;
ch->rqcfg.dst_inc = 1;
break;
case S3C2410_DMASRC_MEM: /* M->P */
ch->req[0].rqtype = MEMTODEV;
ch->req[1].rqtype = MEMTODEV;
ch->rqcfg.src_inc = 1;
ch->rqcfg.dst_inc = 0;
break;
default:
ret = -EINVAL;
goto devcfg_exit;
}
ch->sdaddr = address;
devcfg_exit:
spin_unlock_irqrestore(&res_lock, flags);
return ret;
}
EXPORT_SYMBOL(s3c2410_dma_devconfig);
int s3c2410_dma_getposition(enum dma_ch id, dma_addr_t *src, dma_addr_t *dst)
{
struct s3c_pl330_chan *ch = id_to_chan(id);
struct pl330_chanstatus status;
int ret;
if (!ch || chan_free(ch))
return -EINVAL;
ret = pl330_chan_status(ch->pl330_chan_id, &status);
if (ret < 0)
return ret;
*src = status.src_addr;
*dst = status.dst_addr;
return 0;
}
EXPORT_SYMBOL(s3c2410_dma_getposition);
static irqreturn_t pl330_irq_handler(int irq, void *data)
{
if (pl330_update(data))
return IRQ_HANDLED;
else
return IRQ_NONE;
}
static int pl330_probe(struct platform_device *pdev)
{
struct s3c_pl330_dmac *s3c_pl330_dmac;
struct s3c_pl330_platdata *pl330pd;
struct pl330_info *pl330_info;
struct resource *res;
int i, ret, irq;
pl330pd = pdev->dev.platform_data;
/* Can't do without the list of _32_ peripherals */
if (!pl330pd || !pl330pd->peri) {
dev_err(&pdev->dev, "platform data missing!\n");
return -ENODEV;
}
pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL);
if (!pl330_info)
return -ENOMEM;
pl330_info->pl330_data = NULL;
pl330_info->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
goto probe_err1;
}
request_mem_region(res->start, resource_size(res), pdev->name);
pl330_info->base = ioremap(res->start, resource_size(res));
if (!pl330_info->base) {
ret = -ENXIO;
goto probe_err2;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
ret = irq;
goto probe_err3;
}
ret = request_irq(irq, pl330_irq_handler, 0,
dev_name(&pdev->dev), pl330_info);
if (ret)
goto probe_err4;
ret = pl330_add(pl330_info);
if (ret)
goto probe_err5;
/* Allocate a new DMAC */
s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL);
if (!s3c_pl330_dmac) {
ret = -ENOMEM;
goto probe_err6;
}
/* Hook the info */
s3c_pl330_dmac->pi = pl330_info;
/* No busy channels */
s3c_pl330_dmac->busy_chan = 0;
s3c_pl330_dmac->kmcache = kmem_cache_create(dev_name(&pdev->dev),
sizeof(struct s3c_pl330_xfer), 0, 0, NULL);
if (!s3c_pl330_dmac->kmcache) {
ret = -ENOMEM;
goto probe_err7;
}
/* Get the list of peripherals */
s3c_pl330_dmac->peri = pl330pd->peri;
/* Attach to the list of DMACs */
list_add_tail(&s3c_pl330_dmac->node, &dmac_list);
/* Create a channel for each peripheral in the DMAC
* that is, if it doesn't already exist
*/
for (i = 0; i < PL330_MAX_PERI; i++)
if (s3c_pl330_dmac->peri[i] != DMACH_MAX)
chan_add(s3c_pl330_dmac->peri[i]);
printk(KERN_INFO
"Loaded driver for PL330 DMAC-%d %s\n", pdev->id, pdev->name);
printk(KERN_INFO
"\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
pl330_info->pcfg.data_buf_dep,
pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan,
pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events);
return 0;
probe_err7:
kfree(s3c_pl330_dmac);
probe_err6:
pl330_del(pl330_info);
probe_err5:
free_irq(irq, pl330_info);
probe_err4:
probe_err3:
iounmap(pl330_info->base);
probe_err2:
release_mem_region(res->start, resource_size(res));
probe_err1:
kfree(pl330_info);
return ret;
}
static int pl330_remove(struct platform_device *pdev)
{
struct s3c_pl330_dmac *dmac, *d;
struct s3c_pl330_chan *ch;
unsigned long flags;
int del, found;
if (!pdev->dev.platform_data)
return -EINVAL;
spin_lock_irqsave(&res_lock, flags);
found = 0;
list_for_each_entry(d, &dmac_list, node)
if (d->pi->dev == &pdev->dev) {
found = 1;
break;
}
if (!found) {
spin_unlock_irqrestore(&res_lock, flags);
return 0;
}
dmac = d;
/* Remove all Channels that are managed only by this DMAC */
list_for_each_entry(ch, &chan_list, node) {
/* Only channels that are handled by this DMAC */
if (iface_of_dmac(dmac, ch->id))
del = 1;
else
continue;
/* Don't remove if some other DMAC has it too */
list_for_each_entry(d, &dmac_list, node)
if (d != dmac && iface_of_dmac(d, ch->id)) {
del = 0;
break;
}
if (del) {
spin_unlock_irqrestore(&res_lock, flags);
s3c2410_dma_free(ch->id, ch->client);
spin_lock_irqsave(&res_lock, flags);
list_del(&ch->node);
kfree(ch);
}
}
/* Remove the DMAC */
list_del(&dmac->node);
kfree(dmac);
spin_unlock_irqrestore(&res_lock, flags);
return 0;
}
static struct platform_driver pl330_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "s3c-pl330",
},
.probe = pl330_probe,
.remove = pl330_remove,
};
static int __init pl330_init(void)
{
return platform_driver_register(&pl330_driver);
}
module_init(pl330_init);
static void __exit pl330_exit(void)
{
platform_driver_unregister(&pl330_driver);
return;
}
module_exit(pl330_exit);
MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
MODULE_DESCRIPTION("Driver for PL330 DMA Controller");
MODULE_LICENSE("GPL");
......@@ -142,8 +142,8 @@ config TOUCHSCREEN_FUJITSU
module will be called fujitsu-ts.
config TOUCHSCREEN_S3C2410
tristate "Samsung S3C2410 touchscreen input driver"
depends on ARCH_S3C2410
tristate "Samsung S3C2410/generic touchscreen input driver"
depends on ARCH_S3C2410 || SAMSUNG_DEV_TS
select S3C24XX_ADC
help
Say Y here if you have the s3c2410 touchscreen.
......
......@@ -37,9 +37,7 @@
#include <plat/adc.h>
#include <plat/regs-adc.h>
#include <mach/regs-gpio.h>
#include <mach/ts.h>
#include <plat/ts.h>
#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
......@@ -57,6 +55,8 @@
S3C2410_ADCTSC_AUTO_PST | \
S3C2410_ADCTSC_XY_PST(0))
#define FEAT_PEN_IRQ (1 << 0) /* HAS ADCCLRINTPNDNUP */
/* Per-touchscreen data. */
/**
......@@ -71,6 +71,7 @@
* @irq_tc: The interrupt number for pen up/down interrupt
* @count: The number of samples collected.
* @shift: The log2 of the maximum count to read in one go.
* @features: The features supported by the TSADC MOdule.
*/
struct s3c2410ts {
struct s3c_adc_client *client;
......@@ -83,25 +84,11 @@ struct s3c2410ts {
int irq_tc;
int count;
int shift;
int features;
};
static struct s3c2410ts ts;
/**
* s3c2410_ts_connect - configure gpio for s3c2410 systems
*
* Configure the GPIO for the S3C2410 system, where we have external FETs
* connected to the device (later systems such as the S3C2440 integrate
* these into the device).
*/
static inline void s3c2410_ts_connect(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON);
s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON);
s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON);
s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON);
}
/**
* get_down - return the down state of the pen
* @data0: The data read from ADCDAT0 register.
......@@ -188,6 +175,11 @@ static irqreturn_t stylus_irq(int irq, void *dev_id)
else
dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count);
if (ts.features & FEAT_PEN_IRQ) {
/* Clear pen down/up interrupt */
writel(0x0, ts.io + S3C64XX_ADCCLRINTPNDNUP);
}
return IRQ_HANDLED;
}
......@@ -296,9 +288,9 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
goto err_clk;
}
/* Configure the touchscreen external FETs on the S3C2410 */
if (!platform_get_device_id(pdev)->driver_data)
s3c2410_ts_connect();
/* inititalise the gpio */
if (info->cfg_gpio)
info->cfg_gpio(to_platform_device(ts.dev));
ts.client = s3c_adc_register(pdev, s3c24xx_ts_select,
s3c24xx_ts_conversion, 1);
......@@ -334,6 +326,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
ts.input->id.version = 0x0102;
ts.shift = info->oversampling_shift;
ts.features = platform_get_device_id(pdev)->driver_data;
ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED,
"s3c2410_ts_pen", ts.input);
......@@ -420,15 +413,14 @@ static struct dev_pm_ops s3c_ts_pmops = {
#endif
static struct platform_device_id s3cts_driver_ids[] = {
{ "s3c2410-ts", 0 },
{ "s3c2440-ts", 1 },
{ "s3c64xx-ts", FEAT_PEN_IRQ },
{ }
};
MODULE_DEVICE_TABLE(platform, s3cts_driver_ids);
static struct platform_driver s3c_ts_driver = {
.driver = {
.name = "s3c24xx-ts",
.name = "samsung-ts",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &s3c_ts_pmops,
......
......@@ -534,21 +534,13 @@ config SERIAL_S3C24A0
Serial port support for the Samsung S3C24A0 SoC
config SERIAL_S3C6400
tristate "Samsung S3C6400/S3C6410/S5P6440 Seria port support"
depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440)
tristate "Samsung S3C6400/S3C6410/S5P6440/S5PC100 Serial port support"
depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5PC100)
select SERIAL_SAMSUNG_UARTS_4
default y
help
Serial port support for the Samsung S3C6400, S3C6410 and S5P6440
SoCs
config SERIAL_S5PC100
tristate "Samsung S5PC100 Serial port support"
depends on SERIAL_SAMSUNG && CPU_S5PC100
select SERIAL_SAMSUNG_UARTS_4
default y
help
Serial port support for the Samsung S5PC100 SoCs
Serial port support for the Samsung S3C6400, S3C6410, S5P6440
and S5PC100 SoCs
config SERIAL_S5PV210
tristate "Samsung S5PV210 Serial port support"
......
......@@ -44,7 +44,6 @@ obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o
obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册