From 18403424c4fe5bac509bf52343f5d5407d45ee3a Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 6 Feb 2012 11:22:21 -0800 Subject: ARM: ux500: pass parent pointer to each platform device This patch provides a means for any device within ux500 platform code to allocate its own parent. This is particularly prudent with the introduction of /sys/devices/socX, as a device can now proclaim to be integral part of an SoC, rather than a more generic platform device. Latter patches make good use of this functionality. Signed-off-by: Lee Jones Acked-by: Linus Walleij Signed-off-by: Arnd Bergmann diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 5dde4d4..479ebe0 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -104,7 +104,7 @@ static struct mmci_platform_data mop500_sdi0_data = { #endif }; -static void sdi0_configure(void) +static void sdi0_configure(struct device *parent) { int ret; @@ -123,15 +123,15 @@ static void sdi0_configure(void) gpio_direction_output(sdi0_en, 1); /* Add the device, force v2 to subrevision 1 */ - db8500_add_sdi0(&mop500_sdi0_data, U8500_SDI_V2_PERIPHID); + db8500_add_sdi0(parent, &mop500_sdi0_data, U8500_SDI_V2_PERIPHID); } -void mop500_sdi_tc35892_init(void) +void mop500_sdi_tc35892_init(struct device *parent) { mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD; sdi0_en = GPIO_SDMMC_EN; sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL; - sdi0_configure(); + sdi0_configure(parent); } /* @@ -246,12 +246,13 @@ static struct mmci_platform_data mop500_sdi4_data = { #endif }; -void __init mop500_sdi_init(void) +void __init mop500_sdi_init(struct device *parent) { /* PoP:ed eMMC */ - db8500_add_sdi2(&mop500_sdi2_data, U8500_SDI_V2_PERIPHID); + db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID); /* On-board eMMC */ - db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID); + db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID); + /* * On boards with the TC35892 GPIO expander, sdi0 will finally * be added when the TC35892 initializes and calls @@ -259,31 +260,31 @@ void __init mop500_sdi_init(void) */ } -void __init snowball_sdi_init(void) +void __init snowball_sdi_init(struct device *parent) { /* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */ mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED; /* On-board eMMC */ - db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID); + db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID); /* External Micro SD slot */ mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO; mop500_sdi0_data.cd_invert = true; sdi0_en = SNOWBALL_SDMMC_EN_GPIO; sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO; - sdi0_configure(); + sdi0_configure(parent); } -void __init hrefv60_sdi_init(void) +void __init hrefv60_sdi_init(struct device *parent) { /* PoP:ed eMMC */ - db8500_add_sdi2(&mop500_sdi2_data, U8500_SDI_V2_PERIPHID); + db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID); /* On-board eMMC */ - db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID); + db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID); /* External Micro SD slot */ mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO; sdi0_en = HREFV60_SDMMC_EN_GPIO; sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO; - sdi0_configure(); + sdi0_configure(parent); /* WLAN SDIO channel */ - db8500_add_sdi1(&mop500_sdi1_data, U8500_SDI_V2_PERIPHID); + db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID); } diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 5c00712..f9ce2a1 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -226,7 +226,12 @@ static struct tps6105x_platform_data mop500_tps61052_data = { static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base) { - mop500_sdi_tc35892_init(); + struct device *parent = NULL; +#if 0 + /* FIXME: Is the sdi actually part of tc3589x? */ + parent = tc3589x->dev; +#endif + mop500_sdi_tc35892_init(parent); } static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = { @@ -353,12 +358,12 @@ U8500_I2C_CONTROLLER(1, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); U8500_I2C_CONTROLLER(2, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); U8500_I2C_CONTROLLER(3, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); -static void __init mop500_i2c_init(void) +static void __init mop500_i2c_init(struct device *parent) { - db8500_add_i2c0(&u8500_i2c0_data); - db8500_add_i2c1(&u8500_i2c1_data); - db8500_add_i2c2(&u8500_i2c2_data); - db8500_add_i2c3(&u8500_i2c3_data); + db8500_add_i2c0(parent, &u8500_i2c0_data); + db8500_add_i2c1(parent, &u8500_i2c1_data); + db8500_add_i2c2(parent, &u8500_i2c2_data); + db8500_add_i2c3(parent, &u8500_i2c3_data); } static struct gpio_keys_button mop500_gpio_keys[] = { @@ -451,9 +456,9 @@ static struct pl022_ssp_controller ssp0_platform_data = { .num_chipselect = 5, }; -static void __init mop500_spi_init(void) +static void __init mop500_spi_init(struct device *parent) { - db8500_add_ssp0(&ssp0_platform_data); + db8500_add_ssp0(parent, &ssp0_platform_data); } #ifdef CONFIG_STE_DMA40 @@ -587,11 +592,11 @@ static struct amba_pl011_data uart2_plat = { #endif }; -static void __init mop500_uart_init(void) +static void __init mop500_uart_init(struct device *parent) { - db8500_add_uart0(&uart0_plat); - db8500_add_uart1(&uart1_plat); - db8500_add_uart2(&uart2_plat); + db8500_add_uart0(parent, &uart0_plat); + db8500_add_uart1(parent, &uart1_plat); + db8500_add_uart2(parent, &uart2_plat); } static struct platform_device *snowball_platform_devs[] __initdata = { @@ -603,21 +608,22 @@ static struct platform_device *snowball_platform_devs[] __initdata = { static void __init mop500_init_machine(void) { + struct device *parent = NULL; int i2c0_devs; mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; - u8500_init_devices(); + parent = u8500_init_devices(); mop500_pins_init(); platform_add_devices(mop500_platform_devs, ARRAY_SIZE(mop500_platform_devs)); - mop500_i2c_init(); - mop500_sdi_init(); - mop500_spi_init(); - mop500_uart_init(); + mop500_i2c_init(parent); + mop500_sdi_init(parent); + mop500_spi_init(parent); + mop500_uart_init(parent); i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); @@ -631,19 +637,20 @@ static void __init mop500_init_machine(void) static void __init snowball_init_machine(void) { + struct device *parent = NULL; int i2c0_devs; - u8500_init_devices(); + parent = u8500_init_devices(); snowball_pins_init(); platform_add_devices(snowball_platform_devs, ARRAY_SIZE(snowball_platform_devs)); - mop500_i2c_init(); - snowball_sdi_init(); - mop500_spi_init(); - mop500_uart_init(); + mop500_i2c_init(parent); + snowball_sdi_init(parent); + mop500_spi_init(parent); + mop500_uart_init(parent); i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); @@ -656,6 +663,7 @@ static void __init snowball_init_machine(void) static void __init hrefv60_init_machine(void) { + struct device *parent = NULL; int i2c0_devs; /* @@ -665,17 +673,17 @@ static void __init hrefv60_init_machine(void) */ mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; - u8500_init_devices(); + parent = u8500_init_devices(); hrefv60_pins_init(); platform_add_devices(mop500_platform_devs, ARRAY_SIZE(mop500_platform_devs)); - mop500_i2c_init(); - hrefv60_sdi_init(); - mop500_spi_init(); - mop500_uart_init(); + mop500_i2c_init(parent); + hrefv60_sdi_init(parent); + mop500_spi_init(parent); + mop500_uart_init(parent); i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index f926d3d..3d594c2 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -75,10 +75,10 @@ struct i2c_board_info; -extern void mop500_sdi_init(void); -extern void snowball_sdi_init(void); -extern void hrefv60_sdi_init(void); -extern void mop500_sdi_tc35892_init(void); +extern void mop500_sdi_init(struct device *parent); +extern void snowball_sdi_init(struct device *parent); +extern void hrefv60_sdi_init(struct device *parent); +extern void mop500_sdi_tc35892_init(struct device *parent); void __init mop500_u8500uib_init(void); void __init mop500_stuib_init(void); void __init mop500_pins_init(void); diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c index 63c3f80..836112e 100644 --- a/arch/arm/mach-ux500/board-u5500-sdi.c +++ b/arch/arm/mach-ux500/board-u5500-sdi.c @@ -66,9 +66,9 @@ static struct mmci_platform_data u5500_sdi0_data = { #endif }; -void __init u5500_sdi_init(void) +void __init u5500_sdi_init(struct device *parent) { nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins)); - db5500_add_sdi0(&u5500_sdi0_data); + db5500_add_sdi0(parent, &u5500_sdi0_data); } diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index 9de9e9c..d7a9596 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c @@ -97,9 +97,9 @@ static struct i2c_board_info __initdata u5500_i2c2_devices[] = { }, }; -static void __init u5500_i2c_init(void) +static void __init u5500_i2c_init(struct device *parent) { - db5500_add_i2c2(&u5500_i2c2_data); + db5500_add_i2c2(parent, &u5500_i2c2_data); i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices)); } @@ -126,20 +126,23 @@ static struct platform_device *u5500_platform_devices[] __initdata = { &ab5500_device, }; -static void __init u5500_uart_init(void) +static void __init u5500_uart_init(struct device *parent) { - db5500_add_uart0(NULL); - db5500_add_uart1(NULL); - db5500_add_uart2(NULL); + db5500_add_uart0(parent, NULL); + db5500_add_uart1(parent, NULL); + db5500_add_uart2(parent, NULL); } static void __init u5500_init_machine(void) { - u5500_init_devices(); + struct device *parent = NULL; + + parent = u5500_init_devices(); nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins)); - u5500_i2c_init(); - u5500_sdi_init(); - u5500_uart_init(); + + u5500_i2c_init(parent); + u5500_sdi_init(parent); + u5500_uart_init(parent); platform_add_devices(u5500_platform_devices, ARRAY_SIZE(u5500_platform_devices)); diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index 18aa5c05..c402fd6 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -147,13 +147,13 @@ static resource_size_t __initdata db5500_gpio_base[] = { U5500_GPIOBANK7_BASE, }; -static void __init db5500_add_gpios(void) +static void __init db5500_add_gpios(struct device *parent) { struct nmk_gpio_platform_data pdata = { /* No custom data yet */ }; - dbx500_add_gpios(ARRAY_AND_SIZE(db5500_gpio_base), + dbx500_add_gpios(parent, ARRAY_AND_SIZE(db5500_gpio_base), IRQ_DB5500_GPIO0, &pdata); } @@ -212,14 +212,18 @@ static int usb_db5500_tx_dma_cfg[] = { DB5500_DMA_DEV38_USB_OTG_OEP_8 }; -void __init u5500_init_devices(void) +struct device* __init u5500_init_devices(void) { - db5500_add_gpios(); + /* FIXME: First parameter to be a real parent. */ + db5500_add_gpios(NULL); db5500_pmu_init(); - db5500_dma_init(); - db5500_add_rtc(); - db5500_add_usb(usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg); + db5500_dma_init(NULL); + db5500_add_rtc(NULL); + db5500_add_usb(NULL, usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg); platform_add_devices(db5500_platform_devs, ARRAY_SIZE(db5500_platform_devs)); + + /* FIXME: Return value to be a real parent. */ + return NULL; } diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 7176ee7..1e8a2cb 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -132,13 +132,13 @@ static resource_size_t __initdata db8500_gpio_base[] = { U8500_GPIOBANK8_BASE, }; -static void __init db8500_add_gpios(void) +static void __init db8500_add_gpios(struct device *parent) { struct nmk_gpio_platform_data pdata = { .supports_sleepmode = true, }; - dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), + dbx500_add_gpios(parent, ARRAY_AND_SIZE(db8500_gpio_base), IRQ_DB8500_GPIO0, &pdata); } @@ -167,14 +167,15 @@ static int usb_db8500_tx_dma_cfg[] = { /* * This function is called from the board init */ -void __init u8500_init_devices(void) +struct device* __init u8500_init_devices(void) { - db8500_add_rtc(); - db8500_add_gpios(); - db8500_add_usb(usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); + db8500_add_rtc(NULL); + db8500_add_gpios(NULL); + db8500_add_usb(NULL, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); platform_device_register_simple("cpufreq-u8500", -1, NULL, 0); platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); - return ; + /* FIXME: Return value to be a real parent. */ + return NULL; } diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index c563e54..96be248 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -20,8 +20,9 @@ #include "devices-common.h" struct amba_device * -dbx500_add_amba_device(const char *name, resource_size_t base, - int irq, void *pdata, unsigned int periphid) +dbx500_add_amba_device(struct device *parent, const char *name, + resource_size_t base, int irq, void *pdata, + unsigned int periphid) { struct amba_device *dev; int ret; @@ -109,7 +110,7 @@ dbx500_add_platform_device_4k1irq(const char *name, int id, } static struct platform_device * -dbx500_add_gpio(int id, resource_size_t addr, int irq, +dbx500_add_gpio(struct device *parent, int id, resource_size_t addr, int irq, struct nmk_gpio_platform_data *pdata) { struct resource resources[] = { @@ -130,8 +131,8 @@ dbx500_add_gpio(int id, resource_size_t addr, int irq, pdata, sizeof(*pdata)); } -void dbx500_add_gpios(resource_size_t *base, int num, int irq, - struct nmk_gpio_platform_data *pdata) +void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num, + int irq, struct nmk_gpio_platform_data *pdata) { int first = 0; int i; @@ -141,6 +142,6 @@ void dbx500_add_gpios(resource_size_t *base, int num, int irq, pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first); pdata->num_gpio = 32; - dbx500_add_gpio(i, base[i], irq, pdata); + dbx500_add_gpio(parent, i, base[i], irq, pdata); } } diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index 7825705..f8adff8 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h @@ -9,7 +9,7 @@ #define __DEVICES_COMMON_H extern struct amba_device * -dbx500_add_amba_device(const char *name, resource_size_t base, +dbx500_add_amba_device(struct device *parent, const char *name, resource_size_t base, int irq, void *pdata, unsigned int periphid); extern struct platform_device * @@ -20,43 +20,46 @@ dbx500_add_platform_device_4k1irq(const char *name, int id, struct spi_master_cntlr; static inline struct amba_device * -dbx500_add_msp_spi(const char *name, resource_size_t base, int irq, +dbx500_add_msp_spi(struct device *parent, const char *name, + resource_size_t base, int irq, struct spi_master_cntlr *pdata) { - return dbx500_add_amba_device(name, base, irq, pdata, 0); + return dbx500_add_amba_device(parent, name, base, irq, + pdata, 0); } static inline struct amba_device * -dbx500_add_spi(const char *name, resource_size_t base, int irq, - struct spi_master_cntlr *pdata, +dbx500_add_spi(struct device *parent, const char *name, resource_size_t base, + int irq, struct spi_master_cntlr *pdata, u32 periphid) { - return dbx500_add_amba_device(name, base, irq, pdata, periphid); + return dbx500_add_amba_device(parent, name, base, irq, + pdata, periphid); } struct mmci_platform_data; static inline struct amba_device * -dbx500_add_sdi(const char *name, resource_size_t base, int irq, - struct mmci_platform_data *pdata, - u32 periphid) +dbx500_add_sdi(struct device *parent, const char *name, resource_size_t base, + int irq, struct mmci_platform_data *pdata, u32 periphid) { - return dbx500_add_amba_device(name, base, irq, pdata, periphid); + return dbx500_add_amba_device(parent, name, base, irq, + pdata, periphid); } struct amba_pl011_data; static inline struct amba_device * -dbx500_add_uart(const char *name, resource_size_t base, int irq, - struct amba_pl011_data *pdata) +dbx500_add_uart(struct device *parent, const char *name, resource_size_t base, + int irq, struct amba_pl011_data *pdata) { - return dbx500_add_amba_device(name, base, irq, pdata, 0); + return dbx500_add_amba_device(parent, name, base, irq, pdata, 0); } struct nmk_i2c_controller; static inline struct platform_device * -dbx500_add_i2c(int id, resource_size_t base, int irq, +dbx500_add_i2c(struct device *parent, int id, resource_size_t base, int irq, struct nmk_i2c_controller *pdata) { return dbx500_add_platform_device_4k1irq("nmk-i2c", id, base, irq, @@ -74,14 +77,14 @@ dbx500_add_msp_i2s(int id, resource_size_t base, int irq, } static inline struct amba_device * -dbx500_add_rtc(resource_size_t base, int irq) +dbx500_add_rtc(struct device *parent, resource_size_t base, int irq) { - return dbx500_add_amba_device("rtc-pl031", base, irq, NULL, 0); + return dbx500_add_amba_device(parent, "rtc-pl031", base, irq, NULL, 0); } struct nmk_gpio_platform_data; -void dbx500_add_gpios(resource_size_t *base, int num, int irq, - struct nmk_gpio_platform_data *pdata); +void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num, + int irq, struct nmk_gpio_platform_data *pdata); #endif diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h index 0c4bccd..e709555 100644 --- a/arch/arm/mach-ux500/devices-db5500.h +++ b/arch/arm/mach-ux500/devices-db5500.h @@ -10,70 +10,90 @@ #include "devices-common.h" -#define db5500_add_i2c1(pdata) \ - dbx500_add_i2c(1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata) -#define db5500_add_i2c2(pdata) \ - dbx500_add_i2c(2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata) -#define db5500_add_i2c3(pdata) \ - dbx500_add_i2c(3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata) +#define db5500_add_i2c1(parent, pdata) \ + dbx500_add_i2c(parent, 1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata) +#define db5500_add_i2c2(parent, pdata) \ + dbx500_add_i2c(parent, 2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata) +#define db5500_add_i2c3(parent, pdata) \ + dbx500_add_i2c(parent, 3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata) -#define db5500_add_msp0_i2s(pdata) \ - dbx500_add_msp_i2s(0, U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata) -#define db5500_add_msp1_i2s(pdata) \ - dbx500_add_msp_i2s(1, U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata) -#define db5500_add_msp2_i2s(pdata) \ - dbx500_add_msp_i2s(2, U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata) +#define db5500_add_msp0_spi(parent, pdata) \ + dbx500_add_msp_spi(parent, "msp0", U5500_MSP0_BASE, \ + IRQ_DB5500_MSP0, pdata) +#define db5500_add_msp1_spi(parent, pdata) \ + dbx500_add_msp_spi(parent, "msp1", U5500_MSP1_BASE, \ + IRQ_DB5500_MSP1, pdata) +#define db5500_add_msp2_spi(parent, pdata) \ + dbx500_add_msp_spi(parent, "msp2", U5500_MSP2_BASE, \ + IRQ_DB5500_MSP2, pdata) -#define db5500_add_msp0_spi(pdata) \ - dbx500_add_msp_spi("msp0", U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata) -#define db5500_add_msp1_spi(pdata) \ - dbx500_add_msp_spi("msp1", U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata) -#define db5500_add_msp2_spi(pdata) \ - dbx500_add_msp_spi("msp2", U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata) +#define db5500_add_msp0_spi(parent, pdata) \ + dbx500_add_msp_spi(parent, "msp0", U5500_MSP0_BASE, \ + IRQ_DB5500_MSP0, pdata) +#define db5500_add_msp1_spi(parent, pdata) \ + dbx500_add_msp_spi(parent, "msp1", U5500_MSP1_BASE, \ + IRQ_DB5500_MSP1, pdata) +#define db5500_add_msp2_spi(parent, pdata) \ + dbx500_add_msp_spi(parent, "msp2", U5500_MSP2_BASE, \ + IRQ_DB5500_MSP2, pdata) -#define db5500_add_rtc() \ - dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC); +#define db5500_add_rtc(parent) \ + dbx500_add_rtc(parent, U5500_RTC_BASE, IRQ_DB5500_RTC); -#define db5500_add_usb(rx_cfg, tx_cfg) \ - ux500_add_usb(U5500_USBOTG_BASE, IRQ_DB5500_USBOTG, rx_cfg, tx_cfg) +#define db5500_add_usb(parent, rx_cfg, tx_cfg) \ + ux500_add_usb(parent, U5500_USBOTG_BASE, \ + IRQ_DB5500_USBOTG, rx_cfg, tx_cfg) -#define db5500_add_sdi0(pdata) \ - dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata, \ +#define db5500_add_sdi0(parent, pdata) \ + dbx500_add_sdi(parent, "sdi0", U5500_SDI0_BASE, \ + IRQ_DB5500_SDMMC0, pdata, \ 0x10480180) -#define db5500_add_sdi1(pdata) \ - dbx500_add_sdi("sdi1", U5500_SDI1_BASE, IRQ_DB5500_SDMMC1, pdata, \ +#define db5500_add_sdi1(parent, pdata) \ + dbx500_add_sdi(parent, "sdi1", U5500_SDI1_BASE, \ + IRQ_DB5500_SDMMC1, pdata, \ 0x10480180) -#define db5500_add_sdi2(pdata) \ - dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata \ +#define db5500_add_sdi2(parent, pdata) \ + dbx500_add_sdi(parent, "sdi2", U5500_SDI2_BASE, \ + IRQ_DB5500_SDMMC2, pdata \ 0x10480180) -#define db5500_add_sdi3(pdata) \ - dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata \ +#define db5500_add_sdi3(parent, pdata) \ + dbx500_add_sdi(parent, "sdi3", U5500_SDI3_BASE, \ + IRQ_DB5500_SDMMC3, pdata \ 0x10480180) -#define db5500_add_sdi4(pdata) \ - dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata \ +#define db5500_add_sdi4(parent, pdata) \ + dbx500_add_sdi(parent, "sdi4", U5500_SDI4_BASE, \ + IRQ_DB5500_SDMMC4, pdata \ 0x10480180) /* This one has a bad peripheral ID in the U5500 silicon */ -#define db5500_add_spi0(pdata) \ - dbx500_add_spi("spi0", U5500_SPI0_BASE, IRQ_DB5500_SPI0, pdata, \ +#define db5500_add_spi0(parent, pdata) \ + dbx500_add_spi(parent, "spi0", U5500_SPI0_BASE, \ + IRQ_DB5500_SPI0, pdata, \ 0x10080023) -#define db5500_add_spi1(pdata) \ - dbx500_add_spi("spi1", U5500_SPI1_BASE, IRQ_DB5500_SPI1, pdata, \ +#define db5500_add_spi1(parent, pdata) \ + dbx500_add_spi(parent, "spi1", U5500_SPI1_BASE, \ + IRQ_DB5500_SPI1, pdata, \ 0x10080023) -#define db5500_add_spi2(pdata) \ - dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata \ +#define db5500_add_spi2(parent, pdata) \ + dbx500_add_spi(parent, "spi2", U5500_SPI2_BASE, \ + IRQ_DB5500_SPI2, pdata \ 0x10080023) -#define db5500_add_spi3(pdata) \ - dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata \ +#define db5500_add_spi3(parent, pdata) \ + dbx500_add_spi(parent, "spi3", U5500_SPI3_BASE, \ + IRQ_DB5500_SPI3, pdata \ 0x10080023) -#define db5500_add_uart0(plat) \ - dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0, plat) -#define db5500_add_uart1(plat) \ - dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1, plat) -#define db5500_add_uart2(plat) \ - dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2, plat) -#define db5500_add_uart3(plat) \ - dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3, plat) +#define db5500_add_uart0(parent, plat) \ + dbx500_add_uart(parent, "uart0", U5500_UART0_BASE, \ + IRQ_DB5500_UART0, plat) +#define db5500_add_uart1(parent, plat) \ + dbx500_add_uart(parent, "uart1", U5500_UART1_BASE, \ + IRQ_DB5500_UART1, plat) +#define db5500_add_uart2(parent, plat) \ + dbx500_add_uart(parent, "uart2", U5500_UART2_BASE, \ + IRQ_DB5500_UART2, plat) +#define db5500_add_uart3(parent, plat) \ + dbx500_add_uart(parent, "uart3", U5500_UART3_BASE, \ + IRQ_DB5500_UART3, plat) #endif diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h index cbd4a9a..9bd08ad 100644 --- a/arch/arm/mach-ux500/devices-db8500.h +++ b/arch/arm/mach-ux500/devices-db8500.h @@ -14,7 +14,9 @@ struct ske_keypad_platform_data; struct pl022_ssp_controller; static inline struct platform_device * -db8500_add_ske_keypad(struct ske_keypad_platform_data *pdata) +db8500_add_ske_keypad(struct device *parent, + struct ske_keypad_platform_data *pdata, + size_t size) { return dbx500_add_platform_device_4k1irq("nmk-ske-keypad", -1, U8500_SKE_BASE, @@ -22,80 +24,100 @@ db8500_add_ske_keypad(struct ske_keypad_platform_data *pdata) } static inline struct amba_device * -db8500_add_ssp(const char *name, resource_size_t base, int irq, - struct pl022_ssp_controller *pdata) +db8500_add_ssp(struct device *parent, const char *name, resource_size_t base, + int irq, struct pl022_ssp_controller *pdata) { - return dbx500_add_amba_device(name, base, irq, pdata, 0); + return dbx500_add_amba_device(parent, name, base, irq, pdata, 0); } -#define db8500_add_i2c0(pdata) \ - dbx500_add_i2c(0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata) -#define db8500_add_i2c1(pdata) \ - dbx500_add_i2c(1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata) -#define db8500_add_i2c2(pdata) \ - dbx500_add_i2c(2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata) -#define db8500_add_i2c3(pdata) \ - dbx500_add_i2c(3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata) -#define db8500_add_i2c4(pdata) \ - dbx500_add_i2c(4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata) - -#define db8500_add_msp0_i2s(pdata) \ - dbx500_add_msp_i2s(0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) -#define db8500_add_msp1_i2s(pdata) \ - dbx500_add_msp_i2s(1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) -#define db8500_add_msp2_i2s(pdata) \ - dbx500_add_msp_i2s(2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) -#define db8500_add_msp3_i2s(pdata) \ - dbx500_add_msp_i2s(3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) - -#define db8500_add_msp0_spi(pdata) \ - dbx500_add_msp_spi("msp0", U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) -#define db8500_add_msp1_spi(pdata) \ - dbx500_add_msp_spi("msp1", U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) -#define db8500_add_msp2_spi(pdata) \ - dbx500_add_msp_spi("msp2", U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) -#define db8500_add_msp3_spi(pdata) \ - dbx500_add_msp_spi("msp3", U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) - -#define db8500_add_rtc() \ - dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC); - -#define db8500_add_usb(rx_cfg, tx_cfg) \ - ux500_add_usb(U8500_USBOTG_BASE, IRQ_DB8500_USBOTG, rx_cfg, tx_cfg) - -#define db8500_add_sdi0(pdata, pid) \ - dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata, pid) -#define db8500_add_sdi1(pdata, pid) \ - dbx500_add_sdi("sdi1", U8500_SDI1_BASE, IRQ_DB8500_SDMMC1, pdata, pid) -#define db8500_add_sdi2(pdata, pid) \ - dbx500_add_sdi("sdi2", U8500_SDI2_BASE, IRQ_DB8500_SDMMC2, pdata, pid) -#define db8500_add_sdi3(pdata, pid) \ - dbx500_add_sdi("sdi3", U8500_SDI3_BASE, IRQ_DB8500_SDMMC3, pdata, pid) -#define db8500_add_sdi4(pdata, pid) \ - dbx500_add_sdi("sdi4", U8500_SDI4_BASE, IRQ_DB8500_SDMMC4, pdata, pid) -#define db8500_add_sdi5(pdata, pid) \ - dbx500_add_sdi("sdi5", U8500_SDI5_BASE, IRQ_DB8500_SDMMC5, pdata, pid) - -#define db8500_add_ssp0(pdata) \ - db8500_add_ssp("ssp0", U8500_SSP0_BASE, IRQ_DB8500_SSP0, pdata) -#define db8500_add_ssp1(pdata) \ - db8500_add_ssp("ssp1", U8500_SSP1_BASE, IRQ_DB8500_SSP1, pdata) - -#define db8500_add_spi0(pdata) \ - dbx500_add_spi("spi0", U8500_SPI0_BASE, IRQ_DB8500_SPI0, pdata, 0) -#define db8500_add_spi1(pdata) \ - dbx500_add_spi("spi1", U8500_SPI1_BASE, IRQ_DB8500_SPI1, pdata, 0) -#define db8500_add_spi2(pdata) \ - dbx500_add_spi("spi2", U8500_SPI2_BASE, IRQ_DB8500_SPI2, pdata, 0) -#define db8500_add_spi3(pdata) \ - dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata, 0) - -#define db8500_add_uart0(pdata) \ - dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0, pdata) -#define db8500_add_uart1(pdata) \ - dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1, pdata) -#define db8500_add_uart2(pdata) \ - dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2, pdata) +#define db8500_add_i2c0(parent, pdata) \ + dbx500_add_i2c(parent, 0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata) +#define db8500_add_i2c1(parent, pdata) \ + dbx500_add_i2c(parent, 1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata) +#define db8500_add_i2c2(parent, pdata) \ + dbx500_add_i2c(parent, 2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata) +#define db8500_add_i2c3(parent, pdata) \ + dbx500_add_i2c(parent, 3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata) +#define db8500_add_i2c4(parent, pdata) \ + dbx500_add_i2c(parent, 4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata) + +#define db8500_add_msp0_i2s(parent, pdata) \ + dbx500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) +#define db8500_add_msp1_i2s(parent, pdata) \ + dbx500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) +#define db8500_add_msp2_i2s(parent, pdata) \ + dbx500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) +#define db8500_add_msp3_i2s(parent, pdata) \ + dbx500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) + +#define db8500_add_msp0_spi(parent, pdata) \ + dbx500_add_msp_spi(parent, "msp0", U8500_MSP0_BASE, \ + IRQ_DB8500_MSP0, pdata) +#define db8500_add_msp1_spi(parent, pdata) \ + dbx500_add_msp_spi(parent, "msp1", U8500_MSP1_BASE, \ + IRQ_DB8500_MSP1, pdata) +#define db8500_add_msp2_spi(parent, pdata) \ + dbx500_add_msp_spi(parent, "msp2", U8500_MSP2_BASE, \ + IRQ_DB8500_MSP2, pdata) +#define db8500_add_msp3_spi(parent, pdata) \ + dbx500_add_msp_spi(parent, "msp3", U8500_MSP3_BASE, \ + IRQ_DB8500_MSP1, pdata) + +#define db8500_add_rtc(parent) \ + dbx500_add_rtc(parent, U8500_RTC_BASE, IRQ_DB8500_RTC); + +#define db8500_add_usb(parent, rx_cfg, tx_cfg) \ + ux500_add_usb(parent, U8500_USBOTG_BASE, \ + IRQ_DB8500_USBOTG, rx_cfg, tx_cfg) + +#define db8500_add_sdi0(parent, pdata, pid) \ + dbx500_add_sdi(parent, "sdi0", U8500_SDI0_BASE, \ + IRQ_DB8500_SDMMC0, pdata, pid) +#define db8500_add_sdi1(parent, pdata, pid) \ + dbx500_add_sdi(parent, "sdi1", U8500_SDI1_BASE, \ + IRQ_DB8500_SDMMC1, pdata, pid) +#define db8500_add_sdi2(parent, pdata, pid) \ + dbx500_add_sdi(parent, "sdi2", U8500_SDI2_BASE, \ + IRQ_DB8500_SDMMC2, pdata, pid) +#define db8500_add_sdi3(parent, pdata, pid) \ + dbx500_add_sdi(parent, "sdi3", U8500_SDI3_BASE, \ + IRQ_DB8500_SDMMC3, pdata, pid) +#define db8500_add_sdi4(parent, pdata, pid) \ + dbx500_add_sdi(parent, "sdi4", U8500_SDI4_BASE, \ + IRQ_DB8500_SDMMC4, pdata, pid) +#define db8500_add_sdi5(parent, pdata, pid) \ + dbx500_add_sdi(parent, "sdi5", U8500_SDI5_BASE, \ + IRQ_DB8500_SDMMC5, pdata, pid) + +#define db8500_add_ssp0(parent, pdata) \ + db8500_add_ssp(parent, "ssp0", U8500_SSP0_BASE, \ + IRQ_DB8500_SSP0, pdata) +#define db8500_add_ssp1(parent, pdata) \ + db8500_add_ssp(parent, "ssp1", U8500_SSP1_BASE, \ + IRQ_DB8500_SSP1, pdata) + +#define db8500_add_spi0(parent, pdata) \ + dbx500_add_spi(parent, "spi0", U8500_SPI0_BASE, \ + IRQ_DB8500_SPI0, pdata, 0) +#define db8500_add_spi1(parent, pdata) \ + dbx500_add_spi(parent, "spi1", U8500_SPI1_BASE, \ + IRQ_DB8500_SPI1, pdata, 0) +#define db8500_add_spi2(parent, pdata) \ + dbx500_add_spi(parent, "spi2", U8500_SPI2_BASE, \ + IRQ_DB8500_SPI2, pdata, 0) +#define db8500_add_spi3(parent, pdata) \ + dbx500_add_spi(parent, "spi3", U8500_SPI3_BASE, \ + IRQ_DB8500_SPI3, pdata, 0) + +#define db8500_add_uart0(parent, pdata) \ + dbx500_add_uart(parent, "uart0", U8500_UART0_BASE, \ + IRQ_DB8500_UART0, pdata) +#define db8500_add_uart1(parent, pdata) \ + dbx500_add_uart(parent, "uart1", U8500_UART1_BASE, \ + IRQ_DB8500_UART1, pdata) +#define db8500_add_uart2(parent, pdata) \ + dbx500_add_uart(parent, "uart2", U8500_UART2_BASE, \ + IRQ_DB8500_UART2, pdata) #endif diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c index 1cfab68..41e9470 100644 --- a/arch/arm/mach-ux500/dma-db5500.c +++ b/arch/arm/mach-ux500/dma-db5500.c @@ -125,10 +125,11 @@ static struct platform_device dma40_device = { .resource = dma40_resources }; -void __init db5500_dma_init(void) +void __init db5500_dma_init(struct device *parent) { int ret; + dma40_device.dev.parent = parent; ret = platform_device_register(&dma40_device); if (ret) dev_err(&dma40_device.dev, "unable to register device: %d\n", ret); diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index a7d363f..e46b8b1 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -18,14 +18,14 @@ void __init ux500_map_io(void); extern void __init u5500_map_io(void); extern void __init u8500_map_io(void); -extern void __init u5500_init_devices(void); -extern void __init u8500_init_devices(void); +extern struct device * __init u5500_init_devices(void); +extern struct device * __init u8500_init_devices(void); extern void __init ux500_init_irq(void); -extern void __init u5500_sdi_init(void); +extern void __init u5500_sdi_init(struct device *parent); -extern void __init db5500_dma_init(void); +extern void __init db5500_dma_init(struct device *parent); /* We re-use nomadik_timer for this platform */ extern void nmdk_timer_init(void); diff --git a/arch/arm/mach-ux500/include/mach/usb.h b/arch/arm/mach-ux500/include/mach/usb.h index d3739d4..4c1cc50 100644 --- a/arch/arm/mach-ux500/include/mach/usb.h +++ b/arch/arm/mach-ux500/include/mach/usb.h @@ -20,6 +20,6 @@ struct ux500_musb_board_data { bool (*dma_filter)(struct dma_chan *chan, void *filter_param); }; -void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg, - int *dma_tx_cfg); +void ux500_add_usb(struct device *parent, resource_size_t base, + int irq, int *dma_rx_cfg, int *dma_tx_cfg); #endif diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c index 9f9e1c2..5329a2c 100644 --- a/arch/arm/mach-ux500/usb.c +++ b/arch/arm/mach-ux500/usb.c @@ -140,8 +140,8 @@ static inline void ux500_usb_dma_update_tx_ch_config(int *dst_dev_type) musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx]; } -void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg, - int *dma_tx_cfg) +void ux500_add_usb(struct device *parent, resource_size_t base, int irq, + int *dma_rx_cfg, int *dma_tx_cfg) { ux500_musb_device.resource[0].start = base; ux500_musb_device.resource[0].end = base + SZ_64K - 1; -- cgit v0.10.2 From eda413c228e227d888bc13d210e7c4c6aa62a682 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 6 Feb 2012 11:22:24 -0800 Subject: ARM: ux500: export System-on-Chip information ux500 via sysfs Here we make use of the new System-On-Chip bus driver to export vital SoC information out to userspace via sysfs. This patch provides a data structure of strings to populate the base nodes found in: /sys/devices/soc[0|1|2|...]/[family|machine|revision|soc_id]. It also adds one more node as requested by ST-Ericsson. 'process' depicts the way in which the silicon was manufactured. Signed-off-by: Lee Jones Acked-by: Linus Walleij Signed-off-by: Arnd Bergmann diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 52af004..5cfa539 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -28,6 +28,7 @@ config MACH_U8500 bool "U8500 Development platform" depends on UX500_SOC_DB8500 select TPS6105X + select SOC_BUS help Include support for the mop500 development platform. diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index c402fd6..8f8acfd 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -212,18 +212,32 @@ static int usb_db5500_tx_dma_cfg[] = { DB5500_DMA_DEV38_USB_OTG_OEP_8 }; -struct device* __init u5500_init_devices(void) +static const char *db5500_read_soc_id(void) { - /* FIXME: First parameter to be a real parent. */ - db5500_add_gpios(NULL); + return kasprintf(GFP_KERNEL, "u5500 currently unsupported\n"); +} + +static struct device * __init db5500_soc_device_init(void) +{ + const char *soc_id = db5500_read_soc_id(); + + return ux500_soc_device_init(soc_id); +} + +struct device * __init u5500_init_devices(void) +{ + struct device *parent; + + parent = db5500_soc_device_init(); + + db5500_add_gpios(parent); db5500_pmu_init(); - db5500_dma_init(NULL); - db5500_add_rtc(NULL); - db5500_add_usb(NULL, usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg); + db5500_dma_init(parent); + db5500_add_rtc(parent); + db5500_add_usb(parent, usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg); platform_add_devices(db5500_platform_devs, ARRAY_SIZE(db5500_platform_devs)); - /* FIXME: Return value to be a real parent. */ - return NULL; + return parent; } diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 1e8a2cb..afcde3d 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "devices-db8500.h" #include "ste-dma40-db8500.h" @@ -164,18 +165,38 @@ static int usb_db8500_tx_dma_cfg[] = { DB8500_DMA_DEV39_USB_OTG_OEP_8 }; +static const char *db8500_read_soc_id(void) +{ + void __iomem *uid = __io_address(U8500_BB_UID_BASE); + + return kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x", + readl((u32 *)uid+1), + readl((u32 *)uid+1), readl((u32 *)uid+2), + readl((u32 *)uid+3), readl((u32 *)uid+4)); +} + +static struct device * __init db8500_soc_device_init(void) +{ + const char *soc_id = db8500_read_soc_id(); + + return ux500_soc_device_init(soc_id); +} + /* * This function is called from the board init */ -struct device* __init u8500_init_devices(void) +struct device * __init u8500_init_devices(void) { - db8500_add_rtc(NULL); - db8500_add_gpios(NULL); - db8500_add_usb(NULL, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); + struct device *parent; + + parent = db8500_soc_device_init(); + + db8500_add_rtc(parent); + db8500_add_gpios(parent); + db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); platform_device_register_simple("cpufreq-u8500", -1, NULL, 0); platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); - /* FIXME: Return value to be a real parent. */ - return NULL; + return parent; } diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index f418574..055fb6e 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -2,6 +2,7 @@ * Copyright (C) ST-Ericsson SA 2010 * * Author: Rabin Vincent for ST-Ericsson + * Author: Lee Jones for ST-Ericsson * License terms: GNU General Public License (GPL) version 2 */ @@ -11,6 +12,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -50,3 +55,73 @@ void __init ux500_init_irq(void) db8500_prcmu_early_init(); clk_init(); } + +static const char * __init ux500_get_machine(void) +{ + return kasprintf(GFP_KERNEL, "DB%4x", dbx500_partnumber()); +} + +static const char * __init ux500_get_family(void) +{ + return kasprintf(GFP_KERNEL, "ux500"); +} + +static const char * __init ux500_get_revision(void) +{ + unsigned int rev = dbx500_revision(); + + if (rev == 0x01) + return kasprintf(GFP_KERNEL, "%s", "ED"); + else if (rev >= 0xA0) + return kasprintf(GFP_KERNEL, "%d.%d", + (rev >> 4) - 0xA + 1, rev & 0xf); + + return kasprintf(GFP_KERNEL, "%s", "Unknown"); +} + +static ssize_t ux500_get_process(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + if (dbx500_id.process == 0x00) + return sprintf(buf, "Standard\n"); + + return sprintf(buf, "%02xnm\n", dbx500_id.process); +} + +static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr, + const char *soc_id) +{ + soc_dev_attr->soc_id = soc_id; + soc_dev_attr->machine = ux500_get_machine(); + soc_dev_attr->family = ux500_get_family(); + soc_dev_attr->revision = ux500_get_revision(); +} + +struct device_attribute ux500_soc_attr = + __ATTR(process, S_IRUGO, ux500_get_process, NULL); + +struct device * __init ux500_soc_device_init(const char *soc_id) +{ + struct device *parent; + struct soc_device *soc_dev; + struct soc_device_attribute *soc_dev_attr; + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + return ERR_PTR(-ENOMEM); + + soc_info_populate(soc_dev_attr, soc_id); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR_OR_NULL(soc_dev)) { + kfree(soc_dev_attr); + return NULL; + } + + parent = soc_device_to_device(soc_dev); + if (!IS_ERR_OR_NULL(parent)) + device_create_file(parent, &ux500_soc_attr); + + return parent; +} diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index 80e10f5..9ec20b9 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h @@ -161,4 +161,7 @@ #define U8500_MODEM_BASE 0xe000000 #define U8500_APE_BASE 0x6000000 +/* SoC identification number information */ +#define U8500_BB_UID_BASE (U8500_BACKUPRAM1_BASE + 0xFC0) + #endif diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index e46b8b1..74b43bb 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -27,6 +27,8 @@ extern void __init u5500_sdi_init(struct device *parent); extern void __init db5500_dma_init(struct device *parent); +extern struct device *ux500_soc_device_init(const char *soc_id); + /* We re-use nomadik_timer for this platform */ extern void nmdk_timer_init(void); -- cgit v0.10.2 From b024a0c804356d90b13c072c8bbb444d9e745a66 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 6 Feb 2012 11:22:25 -0800 Subject: ARM: ux500: move top level platform devices in sysfs to /sys/devices/socX At the request of Arnd Bergmann this patch moves all SoC platform devices found in sysfs from /sys/devices/platform to /sys/devices/soc/. It is believed as the devices are SoC specific and a /sys/devices/soc node has recently become available, that this would be a more appropriate place to display the data. Signed-off-by: Lee Jones Acked-by: Linus Walleij Signed-off-by: Arnd Bergmann diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index f9ce2a1..04afcdf 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -610,6 +610,7 @@ static void __init mop500_init_machine(void) { struct device *parent = NULL; int i2c0_devs; + int i; mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; @@ -617,6 +618,9 @@ static void __init mop500_init_machine(void) mop500_pins_init(); + for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) + mop500_platform_devs[i]->dev.parent = parent; + platform_add_devices(mop500_platform_devs, ARRAY_SIZE(mop500_platform_devs)); @@ -639,11 +643,15 @@ static void __init snowball_init_machine(void) { struct device *parent = NULL; int i2c0_devs; + int i; parent = u8500_init_devices(); snowball_pins_init(); + for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++) + snowball_platform_devs[i]->dev.parent = parent; + platform_add_devices(snowball_platform_devs, ARRAY_SIZE(snowball_platform_devs)); @@ -665,6 +673,7 @@ static void __init hrefv60_init_machine(void) { struct device *parent = NULL; int i2c0_devs; + int i; /* * The HREFv60 board removed a GPIO expander and routed @@ -677,6 +686,9 @@ static void __init hrefv60_init_machine(void) hrefv60_pins_init(); + for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) + mop500_platform_devs[i]->dev.parent = parent; + platform_add_devices(mop500_platform_devs, ARRAY_SIZE(mop500_platform_devs)); diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index d7a9596..0ff4be7 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c @@ -136,6 +136,7 @@ static void __init u5500_uart_init(struct device *parent) static void __init u5500_init_machine(void) { struct device *parent = NULL; + int i; parent = u5500_init_devices(); nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins)); @@ -144,6 +145,9 @@ static void __init u5500_init_machine(void) u5500_sdi_init(parent); u5500_uart_init(parent); + for (i = 0; i < ARRAY_SIZE(u5500_platform_devices); i++) + u5500_platform_devices[i]->dev.parent = parent; + platform_add_devices(u5500_platform_devices, ARRAY_SIZE(u5500_platform_devices)); } diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index 8f8acfd..bca47f3 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -227,6 +227,7 @@ static struct device * __init db5500_soc_device_init(void) struct device * __init u5500_init_devices(void) { struct device *parent; + int i; parent = db5500_soc_device_init(); @@ -236,6 +237,9 @@ struct device * __init u5500_init_devices(void) db5500_add_rtc(parent); db5500_add_usb(parent, usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg); + for (i = 0; i < ARRAY_SIZE(db5500_platform_devs); i++) + db5500_platform_devs[i]->dev.parent = parent; + platform_add_devices(db5500_platform_devs, ARRAY_SIZE(db5500_platform_devs)); diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index afcde3d..9bd8163 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -188,6 +188,7 @@ static struct device * __init db8500_soc_device_init(void) struct device * __init u8500_init_devices(void) { struct device *parent; + int i; parent = db8500_soc_device_init(); @@ -195,7 +196,12 @@ struct device * __init u8500_init_devices(void) db8500_add_gpios(parent); db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); - platform_device_register_simple("cpufreq-u8500", -1, NULL, 0); + platform_device_register_data(parent, + "cpufreq-u8500", -1, NULL, 0); + + for (i = 0; i < ARRAY_SIZE(platform_devs); i++) + platform_devs[i]->dev.parent = parent; + platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); return parent; diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index 96be248..96effbd 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -47,6 +47,8 @@ dbx500_add_amba_device(struct device *parent, const char *name, dev->dev.platform_data = pdata; + dev->dev.parent = parent; + ret = amba_device_register(dev, &iomem_resource); if (ret) { kfree(dev); @@ -126,9 +128,14 @@ dbx500_add_gpio(struct device *parent, int id, resource_size_t addr, int irq, } }; - return platform_device_register_resndata(NULL, "gpio", id, - resources, ARRAY_SIZE(resources), - pdata, sizeof(*pdata)); + return platform_device_register_resndata( + parent, + "gpio", + id, + resources, + ARRAY_SIZE(resources), + pdata, + sizeof(*pdata)); } void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num, diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c index 5329a2c..a74af38 100644 --- a/arch/arm/mach-ux500/usb.c +++ b/arch/arm/mach-ux500/usb.c @@ -7,6 +7,7 @@ #include #include #include + #include #include #include @@ -151,5 +152,7 @@ void ux500_add_usb(struct device *parent, resource_size_t base, int irq, ux500_usb_dma_update_rx_ch_config(dma_rx_cfg); ux500_usb_dma_update_tx_ch_config(dma_tx_cfg); + ux500_musb_device.dev.parent = parent; + platform_device_register(&ux500_musb_device); } -- cgit v0.10.2 From 3510ec672319e09fe43bd623b19fcf539c0bd1fa Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 6 Feb 2012 11:22:26 -0800 Subject: ARM: ux500: remove intermediary add_platform_device* functions These are no longer required since a 'parent' pointer is now passed to each registering device. Signed-off-by: Lee Jones Acked-by: Linus Walleij Signed-off-by: Arnd Bergmann diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index 96effbd..c3bc094 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -59,59 +59,6 @@ dbx500_add_amba_device(struct device *parent, const char *name, } static struct platform_device * -dbx500_add_platform_device(const char *name, int id, void *pdata, - struct resource *res, int resnum) -{ - struct platform_device *dev; - int ret; - - dev = platform_device_alloc(name, id); - if (!dev) - return ERR_PTR(-ENOMEM); - - dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - dev->dev.dma_mask = &dev->dev.coherent_dma_mask; - - ret = platform_device_add_resources(dev, res, resnum); - if (ret) - goto out_free; - - dev->dev.platform_data = pdata; - - ret = platform_device_add(dev); - if (ret) - goto out_free; - - return dev; - -out_free: - platform_device_put(dev); - return ERR_PTR(ret); -} - -struct platform_device * -dbx500_add_platform_device_4k1irq(const char *name, int id, - resource_size_t base, - int irq, void *pdata) -{ - struct resource resources[] = { - [0] = { - .start = base, - .end = base + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = irq, - .end = irq, - .flags = IORESOURCE_IRQ, - } - }; - - return dbx500_add_platform_device(name, id, pdata, resources, - ARRAY_SIZE(resources)); -} - -static struct platform_device * dbx500_add_gpio(struct device *parent, int id, resource_size_t addr, int irq, struct nmk_gpio_platform_data *pdata) { diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index f8adff8..39c74ec 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h @@ -8,14 +8,15 @@ #ifndef __DEVICES_COMMON_H #define __DEVICES_COMMON_H -extern struct amba_device * -dbx500_add_amba_device(struct device *parent, const char *name, resource_size_t base, - int irq, void *pdata, unsigned int periphid); +#include +#include +#include +#include -extern struct platform_device * -dbx500_add_platform_device_4k1irq(const char *name, int id, - resource_size_t base, - int irq, void *pdata); +extern struct amba_device * +dbx500_add_amba_device(struct device *parent, const char *name, + resource_size_t base, int irq, void *pdata, + unsigned int periphid); struct spi_master_cntlr; @@ -60,20 +61,25 @@ struct nmk_i2c_controller; static inline struct platform_device * dbx500_add_i2c(struct device *parent, int id, resource_size_t base, int irq, - struct nmk_i2c_controller *pdata) -{ - return dbx500_add_platform_device_4k1irq("nmk-i2c", id, base, irq, - pdata); -} - -struct msp_i2s_platform_data; - -static inline struct platform_device * -dbx500_add_msp_i2s(int id, resource_size_t base, int irq, - struct msp_i2s_platform_data *pdata) + struct nmk_i2c_controller *data) { - return dbx500_add_platform_device_4k1irq("MSP_I2S", id, base, irq, - pdata); + struct resource res[] = { + DEFINE_RES_MEM(base, SZ_4K), + DEFINE_RES_IRQ(irq), + }; + + struct platform_device_info pdevinfo = { + .parent = parent, + .name = "nmk-i2c", + .id = id, + .res = res, + .num_res = ARRAY_SIZE(res), + .data = data, + .size_data = sizeof(*data), + .dma_mask = DMA_BIT_MASK(32), + }; + + return platform_device_register_full(&pdevinfo); } static inline struct amba_device * diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h index 9bd08ad..9fd93e9 100644 --- a/arch/arm/mach-ux500/devices-db8500.h +++ b/arch/arm/mach-ux500/devices-db8500.h @@ -18,9 +18,13 @@ db8500_add_ske_keypad(struct device *parent, struct ske_keypad_platform_data *pdata, size_t size) { - return dbx500_add_platform_device_4k1irq("nmk-ske-keypad", -1, - U8500_SKE_BASE, - IRQ_DB8500_KB, pdata); + struct resource resources[] = { + DEFINE_RES_MEM(U8500_SKE_BASE, SZ_4K), + DEFINE_RES_IRQ(IRQ_DB8500_KB), + }; + + return platform_device_register_resndata(parent, "nmk-ske-keypad", -1, + resources, 2, pdata, size); } static inline struct amba_device * -- cgit v0.10.2 From 35b1498a34390c4927659abb1076b829ad3a7519 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 10 Feb 2012 01:47:41 +0200 Subject: ARM: tegra: cleanup use of chipid register The chipid register contains information about the Tegra variant and revision. We want differentiate between Tegra variants for powergating and secondary core bringup. This patch cleans up the reading and decoding of this register. In subsequent patches the variant will exported as a global variable. Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c index 17fdd40..e2dd342 100644 --- a/arch/arm/mach-tegra/fuse.c +++ b/arch/arm/mach-tegra/fuse.c @@ -33,6 +33,7 @@ int tegra_sku_id; int tegra_cpu_process_id; int tegra_core_process_id; +static int tegra_chip_id; enum tegra_revision tegra_revision; /* The BCT to use at boot is specified by board straps that can be read @@ -65,12 +66,9 @@ static inline bool get_spare_fuse(int bit) return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4); } -static enum tegra_revision tegra_get_revision(void) +static enum tegra_revision tegra_get_revision(u32 id) { - void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804; - u32 id = readl(chip_id); u32 minor_rev = (id >> 16) & 0xf; - u32 chipid = (id >> 8) & 0xff; switch (minor_rev) { case 1: @@ -78,7 +76,8 @@ static enum tegra_revision tegra_get_revision(void) case 2: return TEGRA_REVISION_A02; case 3: - if (chipid == 0x20 && (get_spare_fuse(18) || get_spare_fuse(19))) + if (tegra_chip_id == TEGRA20 && + (get_spare_fuse(18) || get_spare_fuse(19))) return TEGRA_REVISION_A03p; else return TEGRA_REVISION_A03; @@ -91,6 +90,8 @@ static enum tegra_revision tegra_get_revision(void) void tegra_init_fuse(void) { + u32 id; + u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); reg |= 1 << 28; writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); @@ -107,10 +108,13 @@ void tegra_init_fuse(void) reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT); tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT; - tegra_revision = tegra_get_revision(); + id = readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804); + tegra_chip_id = (id >> 8) & 0xff; + + tegra_revision = tegra_get_revision(id); pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n", - tegra_revision_name[tegra_get_revision()], + tegra_revision_name[tegra_revision], tegra_sku_id, tegra_cpu_process_id, tegra_core_process_id); } diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h index d65d2ab..c554572 100644 --- a/arch/arm/mach-tegra/fuse.h +++ b/arch/arm/mach-tegra/fuse.h @@ -35,6 +35,9 @@ enum tegra_revision { #define SKU_ID_AP25E 27 #define SKU_ID_T25E 28 +#define TEGRA20 0x20 +#define TEGRA30 0x30 + extern int tegra_sku_id; extern int tegra_cpu_process_id; extern int tegra_core_process_id; -- cgit v0.10.2 From 4c4ad6695ab8eafe74abaf6c85d068ff496c99d6 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 10 Feb 2012 01:47:42 +0200 Subject: ARM: tegra: export Tegra chipid The powergating and reset handling code needs to differentiate between Tegra variants. Therefore we export the chipid here. Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c index e2dd342..027f2b2 100644 --- a/arch/arm/mach-tegra/fuse.c +++ b/arch/arm/mach-tegra/fuse.c @@ -33,7 +33,7 @@ int tegra_sku_id; int tegra_cpu_process_id; int tegra_core_process_id; -static int tegra_chip_id; +int tegra_chip_id; enum tegra_revision tegra_revision; /* The BCT to use at boot is specified by board straps that can be read diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h index c554572..d2107b2 100644 --- a/arch/arm/mach-tegra/fuse.h +++ b/arch/arm/mach-tegra/fuse.h @@ -41,6 +41,7 @@ enum tegra_revision { extern int tegra_sku_id; extern int tegra_cpu_process_id; extern int tegra_core_process_id; +extern int tegra_chip_id; extern enum tegra_revision tegra_revision; extern int tegra_bct_strapping; -- cgit v0.10.2 From cec60064e4cbbd74e446b2129f640ac0ef5d034e Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 10 Feb 2012 01:47:43 +0200 Subject: ARM: tegra: initialize Tegra chipid early Secondary core bringup relies on the Tegra chipid to distinguish between Tegra variants. Therefore this data needs to be available early on. Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 1cdcda1..04a54c9 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -124,6 +124,7 @@ void __init tegra20_init_early(void) #ifdef CONFIG_ARCH_TEGRA_3x_SOC void __init tegra30_init_early(void) { + tegra_init_fuse(); tegra30_init_clocks(); tegra_init_cache(0x441, 0x551); tegra_pmc_init(); -- cgit v0.10.2 From 26fe681fdaa5c800f1f99e8181631866e50ed8a1 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 10 Feb 2012 01:47:44 +0200 Subject: ARM: tegra: functions to access the flowcontroller Introduce some functions to write to the flowcontroller registers. The flowcontroller controls CPU sleepstates and wakeup. Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index e5373fb..c103008 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -8,6 +8,7 @@ obj-y += timer.o obj-y += pinmux.o obj-y += fuse.o obj-y += pmc.o +obj-y += flowctrl.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_CPU_IDLE) += sleep.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += powergate.o diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c new file mode 100644 index 0000000..fef66a7 --- /dev/null +++ b/arch/arm/mach-tegra/flowctrl.c @@ -0,0 +1,62 @@ +/* + * arch/arm/mach-tegra/flowctrl.c + * + * functions and macros to control the flowcontroller + * + * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include + +#include "flowctrl.h" + +u8 flowctrl_offset_halt_cpu[] = { + FLOW_CTRL_HALT_CPU0_EVENTS, + FLOW_CTRL_HALT_CPU1_EVENTS, + FLOW_CTRL_HALT_CPU1_EVENTS + 8, + FLOW_CTRL_HALT_CPU1_EVENTS + 16, +}; + +u8 flowctrl_offset_cpu_csr[] = { + FLOW_CTRL_CPU0_CSR, + FLOW_CTRL_CPU1_CSR, + FLOW_CTRL_CPU1_CSR + 8, + FLOW_CTRL_CPU1_CSR + 16, +}; + +static void flowctrl_update(u8 offset, u32 value) +{ + void __iomem *addr = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + offset; + + writel(value, addr); + + /* ensure the update has reached the flow controller */ + wmb(); + readl_relaxed(addr); +} + +void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value) +{ + return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value); +} + +void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) +{ + return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value); +} diff --git a/arch/arm/mach-tegra/flowctrl.h b/arch/arm/mach-tegra/flowctrl.h index 74c6efb..1942817 100644 --- a/arch/arm/mach-tegra/flowctrl.h +++ b/arch/arm/mach-tegra/flowctrl.h @@ -34,4 +34,9 @@ #define FLOW_CTRL_HALT_CPU1_EVENTS 0x14 #define FLOW_CTRL_CPU1_CSR 0x18 +#ifndef __ASSEMBLY__ +void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value); +void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value); +#endif + #endif -- cgit v0.10.2 From b36ab9754efbd7429d214b3b03dc9843882571bd Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 10 Feb 2012 01:47:45 +0200 Subject: ARM: tegra: rework Tegra secondary CPU core bringup Prepare the Tegra secondary CPU core bringup code for other Tegra variants. The reset handler is also generalized to allow for future introduction of powersaving modes which turn off the CPU cores. Based on work by: Scott Williams Chris Johnson Colin Cross Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index c103008..7c77a53 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pinmux-tegra30-tables.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o +obj-$(CONFIG_SMP) += reset.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o apbio.o obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S index b5349b2..37d6dd9 100644 --- a/arch/arm/mach-tegra/headsmp.S +++ b/arch/arm/mach-tegra/headsmp.S @@ -1,6 +1,23 @@ #include #include +#include + +#include + +#include "flowctrl.h" +#include "reset.h" + +#define APB_MISC_GP_HIDREV 0x804 +#define PMC_SCRATCH41 0x140 + +#define RESET_DATA(x) ((TEGRA_RESET_##x)*4) + + .macro mov32, reg, val + movw \reg, #:lower16:\val + movt \reg, #:upper16:\val + .endm + .section ".text.head", "ax" __CPUINIT @@ -47,15 +64,117 @@ ENTRY(v7_invalidate_l1) mov pc, lr ENDPROC(v7_invalidate_l1) + ENTRY(tegra_secondary_startup) - msr cpsr_fsxc, #0xd3 bl v7_invalidate_l1 - mrc p15, 0, r0, c0, c0, 5 - and r0, r0, #15 - ldr r1, =0x6000f100 - str r0, [r1] -1: ldr r2, [r1] - cmp r0, r2 - beq 1b + /* Enable coresight */ + mov32 r0, 0xC5ACCE55 + mcr p14, 0, r0, c7, c12, 6 b secondary_startup ENDPROC(tegra_secondary_startup) + + .align L1_CACHE_SHIFT +ENTRY(__tegra_cpu_reset_handler_start) + +/* + * __tegra_cpu_reset_handler: + * + * Common handler for all CPU reset events. + * + * Register usage within the reset handler: + * + * R7 = CPU present (to the OS) mask + * R8 = CPU in LP1 state mask + * R9 = CPU in LP2 state mask + * R10 = CPU number + * R11 = CPU mask + * R12 = pointer to reset handler data + * + * NOTE: This code is copied to IRAM. All code and data accesses + * must be position-independent. + */ + + .align L1_CACHE_SHIFT +ENTRY(__tegra_cpu_reset_handler) + + cpsid aif, 0x13 @ SVC mode, interrupts disabled + mrc p15, 0, r10, c0, c0, 5 @ MPIDR + and r10, r10, #0x3 @ R10 = CPU number + mov r11, #1 + mov r11, r11, lsl r10 @ R11 = CPU mask + adr r12, __tegra_cpu_reset_handler_data + +#ifdef CONFIG_SMP + /* Does the OS know about this CPU? */ + ldr r7, [r12, #RESET_DATA(MASK_PRESENT)] + tst r7, r11 @ if !present + bleq __die @ CPU not present (to OS) +#endif + +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + /* Are we on Tegra20? */ + mov32 r6, TEGRA_APB_MISC_BASE + ldr r0, [r6, #APB_MISC_GP_HIDREV] + and r0, r0, #0xff00 + cmp r0, #(0x20 << 8) + bne 1f + /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */ + mov32 r6, TEGRA_PMC_BASE + mov r0, #0 + cmp r10, #0 + strne r0, [r6, #PMC_SCRATCH41] +1: +#endif + +#ifdef CONFIG_SMP + /* + * Can only be secondary boot (initial or hotplug) but CPU 0 + * cannot be here. + */ + cmp r10, #0 + bleq __die @ CPU0 cannot be here + ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)] + cmp lr, #0 + bleq __die @ no secondary startup handler + bx lr +#endif + +/* + * We don't know why the CPU reset. Just kill it. + * The LR register will contain the address we died at + 4. + */ + +__die: + sub lr, lr, #4 + mov32 r7, TEGRA_PMC_BASE + str lr, [r7, #PMC_SCRATCH41] + + mov32 r7, TEGRA_CLK_RESET_BASE + + /* Are we on Tegra20? */ + mov32 r6, TEGRA_APB_MISC_BASE + ldr r0, [r6, #APB_MISC_GP_HIDREV] + and r0, r0, #0xff00 + cmp r0, #(0x20 << 8) + bne 1f + +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + mov32 r0, 0x1111 + mov r1, r0, lsl r10 + str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET +#endif +1: + /* If the CPU still isn't dead, just spin here. */ + b . +ENDPROC(__tegra_cpu_reset_handler) + + .align L1_CACHE_SHIFT + .type __tegra_cpu_reset_handler_data, %object + .globl __tegra_cpu_reset_handler_data +__tegra_cpu_reset_handler_data: + .rept TEGRA_RESET_DATA_SIZE + .long 0 + .endr + .align L1_CACHE_SHIFT + +ENTRY(__tegra_cpu_reset_handler_end) diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h index 67644c9..cff672a 100644 --- a/arch/arm/mach-tegra/include/mach/iomap.h +++ b/arch/arm/mach-tegra/include/mach/iomap.h @@ -113,6 +113,9 @@ #define TEGRA_AHB_GIZMO_BASE 0x6000C004 #define TEGRA_AHB_GIZMO_SIZE 0x10C +#define TEGRA_SB_BASE 0x6000C200 +#define TEGRA_SB_SIZE 256 + #define TEGRA_STATMON_BASE 0x6000C400 #define TEGRA_STATMON_SIZE SZ_1K diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 7d2b5d0..79a241a 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -26,18 +26,26 @@ #include +#include "fuse.h" +#include "flowctrl.h" +#include "reset.h" + extern void tegra_secondary_startup(void); -static DEFINE_SPINLOCK(boot_lock); static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); #define EVP_CPU_RESET_VECTOR \ (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100) #define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \ (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c) +#define CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET \ + (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x340) #define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \ (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344) +#define CPU_CLOCK(cpu) (0x1<<(8+cpu)) +#define CPU_RESET(cpu) (0x1111ul<<(cpu)) + void __cpuinit platform_secondary_init(unsigned int cpu) { /* @@ -47,63 +55,62 @@ void __cpuinit platform_secondary_init(unsigned int cpu) */ gic_secondary_init(0); - /* - * Synchronise with the boot thread. - */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +static int tegra20_power_up_cpu(unsigned int cpu) { - unsigned long old_boot_vector; - unsigned long boot_vector; - unsigned long timeout; u32 reg; - /* - * set synchronisation state between this boot processor - * and the secondary one - */ - spin_lock(&boot_lock); - - - /* set the reset vector to point to the secondary_startup routine */ - - boot_vector = virt_to_phys(tegra_secondary_startup); - old_boot_vector = readl(EVP_CPU_RESET_VECTOR); - writel(boot_vector, EVP_CPU_RESET_VECTOR); - - /* enable cpu clock on cpu1 */ + /* Enable the CPU clock. */ + reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX); + writel(reg & ~CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX); + barrier(); reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX); - writel(reg & ~(1<<9), CLK_RST_CONTROLLER_CLK_CPU_CMPLX); - - reg = (1<<13) | (1<<9) | (1<<5) | (1<<1); - writel(reg, CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR); - smp_wmb(); - flush_cache_all(); + /* Clear flow controller CSR. */ + flowctrl_write_cpu_csr(cpu, 0); - /* unhalt the cpu */ - writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x14); + return 0; +} - timeout = jiffies + (1 * HZ); - while (time_before(jiffies, timeout)) { - if (readl(EVP_CPU_RESET_VECTOR) != boot_vector) - break; - udelay(10); - } +int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + int status; - /* put the old boot vector back */ - writel(old_boot_vector, EVP_CPU_RESET_VECTOR); + /* Force the CPU into reset. The CPU must remain in reset when the + * flow controller state is cleared (which will cause the flow + * controller to stop driving reset if the CPU has been power-gated + * via the flow controller). This will have no effect on first boot + * of the CPU since it should already be in reset. + */ + writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); + dmb(); /* - * now the secondary core is starting up let it run its - * calibrations, then wait for it to finish + * Unhalt the CPU. If the flow controller was used to power-gate the + * CPU this will cause the flow controller to stop driving reset. + * The CPU will remain in reset because the clock and reset block + * is now driving reset. */ - spin_unlock(&boot_lock); + flowctrl_write_cpu_halt(cpu, 0); + + switch (tegra_chip_id) { + case TEGRA20: + status = tegra20_power_up_cpu(cpu); + break; + default: + status = -EINVAL; + break; + } - return 0; + if (status) + goto done; + + /* Take the CPU out of reset. */ + writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR); + wmb(); +done: + return status; } /* @@ -128,6 +135,6 @@ void __init smp_init_cpus(void) void __init platform_smp_prepare_cpus(unsigned int max_cpus) { - + tegra_cpu_reset_handler_init(); scu_enable(scu_base); } diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c new file mode 100644 index 0000000..4d6a2ee --- /dev/null +++ b/arch/arm/mach-tegra/reset.c @@ -0,0 +1,84 @@ +/* + * arch/arm/mach-tegra/reset.c + * + * Copyright (C) 2011,2012 NVIDIA Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "reset.h" +#include "fuse.h" + +#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \ + TEGRA_IRAM_RESET_HANDLER_OFFSET) + +static bool is_enabled; + +static void tegra_cpu_reset_handler_enable(void) +{ + void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE); + void __iomem *evp_cpu_reset = + IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100); + void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE); + u32 reg; + + BUG_ON(is_enabled); + BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE); + + memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, + tegra_cpu_reset_handler_size); + + /* + * NOTE: This must be the one and only write to the EVP CPU reset + * vector in the entire system. + */ + writel(TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset, + evp_cpu_reset); + wmb(); + reg = readl(evp_cpu_reset); + + /* + * Prevent further modifications to the physical reset vector. + * NOTE: Has no effect on chips prior to Tegra30. + */ + if (tegra_chip_id != TEGRA20) { + reg = readl(sb_ctrl); + reg |= 2; + writel(reg, sb_ctrl); + wmb(); + } + + is_enabled = true; +} + +void __init tegra_cpu_reset_handler_init(void) +{ + +#ifdef CONFIG_SMP + __tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] = + *((u32 *)cpu_present_mask); + __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] = + virt_to_phys((void *)tegra_secondary_startup); +#endif + + tegra_cpu_reset_handler_enable(); +} diff --git a/arch/arm/mach-tegra/reset.h b/arch/arm/mach-tegra/reset.h new file mode 100644 index 0000000..de88bf8 --- /dev/null +++ b/arch/arm/mach-tegra/reset.h @@ -0,0 +1,50 @@ +/* + * arch/arm/mach-tegra/reset.h + * + * CPU reset dispatcher. + * + * Copyright (c) 2011, NVIDIA Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef __MACH_TEGRA_RESET_H +#define __MACH_TEGRA_RESET_H + +#define TEGRA_RESET_MASK_PRESENT 0 +#define TEGRA_RESET_MASK_LP1 1 +#define TEGRA_RESET_MASK_LP2 2 +#define TEGRA_RESET_STARTUP_SECONDARY 3 +#define TEGRA_RESET_STARTUP_LP2 4 +#define TEGRA_RESET_STARTUP_LP1 5 +#define TEGRA_RESET_DATA_SIZE 6 + +#ifndef __ASSEMBLY__ + +extern unsigned long __tegra_cpu_reset_handler_data[TEGRA_RESET_DATA_SIZE]; + +void __tegra_cpu_reset_handler_start(void); +void __tegra_cpu_reset_handler(void); +void __tegra_cpu_reset_handler_end(void); +void tegra_secondary_startup(void); + +#define tegra_cpu_reset_handler_offset \ + ((u32)__tegra_cpu_reset_handler - \ + (u32)__tegra_cpu_reset_handler_start) + +#define tegra_cpu_reset_handler_size \ + (__tegra_cpu_reset_handler_end - \ + __tegra_cpu_reset_handler_start) + +void __init tegra_cpu_reset_handler_init(void); + +#endif +#endif -- cgit v0.10.2 From 8f5d6f1b46df37ad3eea8f4e09bbe4bbe1bfc6c3 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 10 Feb 2012 01:47:46 +0200 Subject: ARM: tegra: prepare powergate.c for multiple variants Prepare the powergating code for other Tegra variants which have a different number of powerdomains. Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h index 39c396d..36846dc 100644 --- a/arch/arm/mach-tegra/include/mach/powergate.h +++ b/arch/arm/mach-tegra/include/mach/powergate.h @@ -27,7 +27,6 @@ #define TEGRA_POWERGATE_VDEC 4 #define TEGRA_POWERGATE_L2 5 #define TEGRA_POWERGATE_MPE 6 -#define TEGRA_NUM_POWERGATE 7 int tegra_powergate_power_on(int id); int tegra_powergate_power_off(int id); diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c index 9483064..9b828f2 100644 --- a/arch/arm/mach-tegra/powergate.c +++ b/arch/arm/mach-tegra/powergate.c @@ -31,6 +31,8 @@ #include #include +#include "fuse.h" + #define PWRGATE_TOGGLE 0x30 #define PWRGATE_TOGGLE_START (1 << 8) @@ -38,6 +40,8 @@ #define PWRGATE_STATUS 0x38 +static int tegra_num_powerdomains; + static DEFINE_SPINLOCK(tegra_powergate_lock); static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); @@ -75,7 +79,7 @@ static int tegra_powergate_set(int id, bool new_state) int tegra_powergate_power_on(int id) { - if (id < 0 || id >= TEGRA_NUM_POWERGATE) + if (id < 0 || id >= tegra_num_powerdomains) return -EINVAL; return tegra_powergate_set(id, true); @@ -83,17 +87,18 @@ int tegra_powergate_power_on(int id) int tegra_powergate_power_off(int id) { - if (id < 0 || id >= TEGRA_NUM_POWERGATE) + if (id < 0 || id >= tegra_num_powerdomains) return -EINVAL; return tegra_powergate_set(id, false); } -static bool tegra_powergate_is_powered(int id) +static int tegra_powergate_is_powered(int id) { u32 status; - WARN_ON(id < 0 || id >= TEGRA_NUM_POWERGATE); + if (id < 0 || id >= tegra_num_powerdomains) + return -EINVAL; status = pmc_read(PWRGATE_STATUS) & (1 << id); return !!status; @@ -103,7 +108,7 @@ int tegra_powergate_remove_clamping(int id) { u32 mask; - if (id < 0 || id >= TEGRA_NUM_POWERGATE) + if (id < 0 || id >= tegra_num_powerdomains) return -EINVAL; /* @@ -156,6 +161,22 @@ err_power: return ret; } +int __init tegra_powergate_init(void) +{ + switch (tegra_chip_id) { + case TEGRA20: + tegra_num_powerdomains = 7; + break; + default: + /* Unknown Tegra variant. Disable powergating */ + tegra_num_powerdomains = 0; + break; + } + + return 0; +} +arch_initcall(tegra_powergate_init); + #ifdef CONFIG_DEBUG_FS static const char * const powergate_name[] = { @@ -175,7 +196,7 @@ static int powergate_show(struct seq_file *s, void *data) seq_printf(s, " powergate powered\n"); seq_printf(s, "------------------\n"); - for (i = 0; i < TEGRA_NUM_POWERGATE; i++) + for (i = 0; i < tegra_num_powerdomains; i++) seq_printf(s, " %9s %7s\n", powergate_name[i], tegra_powergate_is_powered(i) ? "yes" : "no"); return 0; -- cgit v0.10.2 From 6ac8cb5c213a3f3cfc243ef2f635794bd4b55c60 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 10 Feb 2012 01:47:47 +0200 Subject: ARM: tegra: export tegra_powergate_is_powered() Export tegra_powergate_is_powered(). This function will be used by the Tegra30 code to bringup secondary CPU cores. Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h index 36846dc..0ec8ce1 100644 --- a/arch/arm/mach-tegra/include/mach/powergate.h +++ b/arch/arm/mach-tegra/include/mach/powergate.h @@ -28,6 +28,7 @@ #define TEGRA_POWERGATE_L2 5 #define TEGRA_POWERGATE_MPE 6 +int tegra_powergate_is_powered(int id); int tegra_powergate_power_on(int id); int tegra_powergate_power_off(int id); int tegra_powergate_remove_clamping(int id); diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c index 9b828f2..984bbdf 100644 --- a/arch/arm/mach-tegra/powergate.c +++ b/arch/arm/mach-tegra/powergate.c @@ -93,7 +93,7 @@ int tegra_powergate_power_off(int id) return tegra_powergate_set(id, false); } -static int tegra_powergate_is_powered(int id) +int tegra_powergate_is_powered(int id) { u32 status; -- cgit v0.10.2 From 6cafa97d3ca6a480dc39e20bb2d12ec2c5ca025e Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 10 Feb 2012 01:47:48 +0200 Subject: ARM: tegra: add support for Tegra30 powerdomains Add support for the new powerdomains in Tegra30 such as extra CPU cores and the SATA domain. Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h index 0ec8ce1..ca41186 100644 --- a/arch/arm/mach-tegra/include/mach/powergate.h +++ b/arch/arm/mach-tegra/include/mach/powergate.h @@ -27,6 +27,16 @@ #define TEGRA_POWERGATE_VDEC 4 #define TEGRA_POWERGATE_L2 5 #define TEGRA_POWERGATE_MPE 6 +#define TEGRA_POWERGATE_HEG 7 +#define TEGRA_POWERGATE_SATA 8 +#define TEGRA_POWERGATE_CPU1 9 +#define TEGRA_POWERGATE_CPU2 10 +#define TEGRA_POWERGATE_CPU3 11 +#define TEGRA_POWERGATE_CELP 12 +#define TEGRA_POWERGATE_3D1 13 + +#define TEGRA_POWERGATE_CPU0 TEGRA_POWERGATE_CPU +#define TEGRA_POWERGATE_3D0 TEGRA_POWERGATE_3D int tegra_powergate_is_powered(int id); int tegra_powergate_power_on(int id); diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c index 984bbdf..7120ad7 100644 --- a/arch/arm/mach-tegra/powergate.c +++ b/arch/arm/mach-tegra/powergate.c @@ -167,6 +167,9 @@ int __init tegra_powergate_init(void) case TEGRA20: tegra_num_powerdomains = 7; break; + case TEGRA30: + tegra_num_powerdomains = 14; + break; default: /* Unknown Tegra variant. Disable powergating */ tegra_num_powerdomains = 0; -- cgit v0.10.2 From 65fe31da5cede3597938b0f3bba99f604369018d Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 10 Feb 2012 01:47:49 +0200 Subject: ARM: tegra: support for Tegra30 CPU powerdomains Secondary CPU powerdomains can be powergated on Tegra30. Add the necessary functions to do this. This will be used to boot the secondary CPUs later on. Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 04a54c9..09dc37f 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -28,6 +28,7 @@ #include #include +#include #include "board.h" #include "clock.h" @@ -119,6 +120,7 @@ void __init tegra20_init_early(void) tegra_clk_init_from_table(tegra20_clk_init_table); tegra_init_cache(0x331, 0x441); tegra_pmc_init(); + tegra_powergate_init(); } #endif #ifdef CONFIG_ARCH_TEGRA_3x_SOC @@ -128,5 +130,6 @@ void __init tegra30_init_early(void) tegra30_init_clocks(); tegra_init_cache(0x441, 0x551); tegra_pmc_init(); + tegra_powergate_init(); } #endif diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h index ca41186..4752b1a 100644 --- a/arch/arm/mach-tegra/include/mach/powergate.h +++ b/arch/arm/mach-tegra/include/mach/powergate.h @@ -38,6 +38,9 @@ #define TEGRA_POWERGATE_CPU0 TEGRA_POWERGATE_CPU #define TEGRA_POWERGATE_3D0 TEGRA_POWERGATE_3D +int __init tegra_powergate_init(void); + +int tegra_cpu_powergate_id(int cpuid); int tegra_powergate_is_powered(int id); int tegra_powergate_power_on(int id); int tegra_powergate_power_off(int id); diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c index 7120ad7..c238699 100644 --- a/arch/arm/mach-tegra/powergate.c +++ b/arch/arm/mach-tegra/powergate.c @@ -41,6 +41,14 @@ #define PWRGATE_STATUS 0x38 static int tegra_num_powerdomains; +static int tegra_num_cpu_domains; +static u8 *tegra_cpu_domains; +static u8 tegra30_cpu_domains[] = { + TEGRA_POWERGATE_CPU0, + TEGRA_POWERGATE_CPU1, + TEGRA_POWERGATE_CPU2, + TEGRA_POWERGATE_CPU3, +}; static DEFINE_SPINLOCK(tegra_powergate_lock); @@ -161,6 +169,14 @@ err_power: return ret; } +int tegra_cpu_powergate_id(int cpuid) +{ + if (cpuid > 0 && cpuid < tegra_num_cpu_domains) + return tegra_cpu_domains[cpuid]; + + return -EINVAL; +} + int __init tegra_powergate_init(void) { switch (tegra_chip_id) { @@ -169,6 +185,8 @@ int __init tegra_powergate_init(void) break; case TEGRA30: tegra_num_powerdomains = 14; + tegra_num_cpu_domains = 4; + tegra_cpu_domains = tegra30_cpu_domains; break; default: /* Unknown Tegra variant. Disable powergating */ @@ -178,7 +196,6 @@ int __init tegra_powergate_init(void) return 0; } -arch_initcall(tegra_powergate_init); #ifdef CONFIG_DEBUG_FS -- cgit v0.10.2 From 86e51a2ee471062184d2f74b46c45d344a2b9b38 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Fri, 10 Feb 2012 01:47:50 +0200 Subject: ARM: tegra: support for secondary cores on Tegra30 Add support for bringing up secondary cores on Tegra30. On Tegra30 secondary CPU cores are powergated, so we need to turn on the domains before we can bring the CPU cores online. Bringing secondary cores online happens early during the sytem boot, so we call powergating initialization from platform early_init function. Based on work by: Scott Williams Colin Cross Alex Frid Signed-off-by: Peter De Schrijver Acked-by: Stephen Warren Tested-by: Stephen Warren Acked-by: Colin Cross Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S index 37d6dd9..fef9c2c 100644 --- a/arch/arm/mach-tegra/headsmp.S +++ b/arch/arm/mach-tegra/headsmp.S @@ -164,6 +164,38 @@ __die: str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET #endif 1: +#ifdef CONFIG_ARCH_TEGRA_3x_SOC + mov32 r6, TEGRA_FLOW_CTRL_BASE + + cmp r10, #0 + moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS + moveq r2, #FLOW_CTRL_CPU0_CSR + movne r1, r10, lsl #3 + addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8) + addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8) + + /* Clear CPU "event" and "interrupt" flags and power gate + it when halting but not before it is in the "WFI" state. */ + ldr r0, [r6, +r2] + orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG + orr r0, r0, #FLOW_CTRL_CSR_ENABLE + str r0, [r6, +r2] + + /* Unconditionally halt this CPU */ + mov r0, #FLOW_CTRL_WAITEVENT + str r0, [r6, +r1] + ldr r0, [r6, +r1] @ memory barrier + + dsb + isb + wfi @ CPU should be power gated here + + /* If the CPU didn't power gate above just kill it's clock. */ + + mov r0, r11, lsl #8 + str r0, [r7, #348] @ CLK_CPU_CMPLX_SET +#endif + /* If the CPU still isn't dead, just spin here. */ b . ENDPROC(__tegra_cpu_reset_handler) diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 79a241a..1a208db 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -24,7 +24,9 @@ #include #include +#include #include +#include #include "fuse.h" #include "flowctrl.h" @@ -42,6 +44,8 @@ static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x340) #define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \ (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344) +#define CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR \ + (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x34c) #define CPU_CLOCK(cpu) (0x1<<(8+cpu)) #define CPU_RESET(cpu) (0x1111ul<<(cpu)) @@ -73,11 +77,52 @@ static int tegra20_power_up_cpu(unsigned int cpu) return 0; } +static int tegra30_power_up_cpu(unsigned int cpu) +{ + u32 reg; + int ret, pwrgateid; + unsigned long timeout; + + pwrgateid = tegra_cpu_powergate_id(cpu); + if (pwrgateid < 0) + return pwrgateid; + + /* If this is the first boot, toggle powergates directly. */ + if (!tegra_powergate_is_powered(pwrgateid)) { + ret = tegra_powergate_power_on(pwrgateid); + if (ret) + return ret; + + /* Wait for the power to come up. */ + timeout = jiffies + 10*HZ; + while (tegra_powergate_is_powered(pwrgateid)) { + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + udelay(10); + } + } + + /* CPU partition is powered. Enable the CPU clock. */ + writel(CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR); + reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR); + udelay(10); + + /* Remove I/O clamps. */ + ret = tegra_powergate_remove_clamping(pwrgateid); + udelay(10); + + /* Clear flow controller CSR. */ + flowctrl_write_cpu_csr(cpu, 0); + + return 0; +} + int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) { int status; - /* Force the CPU into reset. The CPU must remain in reset when the + /* + * Force the CPU into reset. The CPU must remain in reset when the * flow controller state is cleared (which will cause the flow * controller to stop driving reset if the CPU has been power-gated * via the flow controller). This will have no effect on first boot @@ -98,6 +143,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) case TEGRA20: status = tegra20_power_up_cpu(cpu); break; + case TEGRA30: + status = tegra30_power_up_cpu(cpu); + break; default: status = -EINVAL; break; -- cgit v0.10.2 From 8c690fdf465be9d97229f6bb0e6346624d6753a9 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 2 Feb 2012 12:24:19 -0700 Subject: ARM: dt: Explicitly configure all serial ports on Tegra Cardhu The ports are used as follows: UART1/A: Routed to debug dongle UART2/B: GPS UART3/C: Bluetooth UART4/D: Routed to debug dongle UART5/E: Not connected The debug dongle has jumpers to connect either UART1/A or UART4/D to the DB-9 connector. UART1/A is typically used on Cardhu, and is the option we assume here. For now, only enable UART1/A, and explicitly disable all other ports. The explicit disable prevents the message "of_serial 70006040.serial: no clock-frequency property set" being printed during boot. Enabling the other ports requires their clocks to be enabled, or accesses to the registers will hang. At present, this requires adding entries into board-dt-tegra30.c's tegra_dt_clk_init_table[]. Lets punt on that and wait for the common clock bindings to set this all up, although that will also requiring adding clock support to 8250.c. While we're at it, fix board-dt-tegra30.c to enable the correct clock for the debug UART. We got away with this before, because the bootloader already enabled it. Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson diff --git a/arch/arm/boot/dts/tegra-cardhu.dts b/arch/arm/boot/dts/tegra-cardhu.dts index 70c41fc..0419690 100644 --- a/arch/arm/boot/dts/tegra-cardhu.dts +++ b/arch/arm/boot/dts/tegra-cardhu.dts @@ -14,6 +14,22 @@ clock-frequency = < 408000000 >; }; + serial@70006040 { + status = "disable"; + }; + + serial@70006200 { + status = "disable"; + }; + + serial@70006300 { + status = "disable"; + }; + + serial@70006400 { + status = "disable"; + }; + i2c@7000c000 { clock-frequency = <100000>; }; diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c index b4124b1..11f7abd 100644 --- a/arch/arm/mach-tegra/board-dt-tegra30.c +++ b/arch/arm/mach-tegra/board-dt-tegra30.c @@ -56,7 +56,7 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = { static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = { /* name parent rate enabled */ - { "uartd", "pll_p", 408000000, true }, + { "uarta", "pll_p", 408000000, true }, { NULL, NULL, 0, 0}, }; -- cgit v0.10.2 From 790254665293fd5f0961a4bb6e2ab07d5d311522 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Mon, 12 Mar 2012 21:17:02 -0700 Subject: ARM: EXYNOS: Add clkdev lookup entry for lcd clock The framebuffer driver needs the clock named 'lcd' as its bus clock but the equivalent clock on Exynos4 is named as 'fimd'. Hence, create a clkdev lookup entry with the name 'lcd' that references the 'fimd' clock. Signed-off-by: Tushar Behera Acked-by: Jingoo Han Reviewed-by: Sylwester Nawrocki [kgene.kim@samsung.com: rebased on top of latest samsung tree] Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c index 1bc0b75..6504d8b 100644 --- a/arch/arm/mach-exynos/clock-exynos4.c +++ b/arch/arm/mach-exynos/clock-exynos4.c @@ -491,11 +491,6 @@ static struct clk exynos4_init_clocks_off[] = { .enable = exynos4_clk_ip_cam_ctrl, .ctrlbit = (1 << 3), }, { - .name = "fimd", - .devname = "exynos4-fb.0", - .enable = exynos4_clk_ip_lcd0_ctrl, - .ctrlbit = (1 << 0), - }, { .name = "hsmmc", .devname = "s3c-sdhci.0", .parent = &exynos4_clk_aclk_133.clk, @@ -791,6 +786,13 @@ static struct clk exynos4_clk_mdma1 = { .ctrlbit = ((1 << 8) | (1 << 5) | (1 << 2)), }; +static struct clk exynos4_clk_fimd0 = { + .name = "fimd", + .devname = "exynos4-fb.0", + .enable = exynos4_clk_ip_lcd0_ctrl, + .ctrlbit = (1 << 0), +}; + struct clk *exynos4_clkset_group_list[] = { [0] = &clk_ext_xtal_mux, [1] = &clk_xusbxti, @@ -1310,6 +1312,7 @@ static struct clk *exynos4_clk_cdev[] = { &exynos4_clk_pdma0, &exynos4_clk_pdma1, &exynos4_clk_mdma1, + &exynos4_clk_fimd0, }; static struct clksrc_clk *exynos4_clksrc_cdev[] = { @@ -1336,6 +1339,7 @@ static struct clk_lookup exynos4_clk_lookup[] = { CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk), CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk), CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk), + CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0), CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0), CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1), CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1), -- cgit v0.10.2 From 906c789c64ac18c3fa536fe9d3c37e44b5914af1 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sat, 11 Feb 2012 21:27:08 +0900 Subject: ARM: EXYNOS: to declare static for mach-exynos/common.c According to commit cc511b8d84d8 ("ARM: 7257/1: EXYNOS: introduce arch/arm/mach-exynos/common.[ch]"), we don't need to declare extern for exynos4_map_io(), exynos4_init_clocks(), exynos4_init_uarts(), and exynos_init(). And the exynos4210_register_clocks() and exynos4212_register_clocks depend on each SoC not ARCH_EXYNOS4. So this patch fixed above. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 34e8190..a1f8a99 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -50,6 +50,11 @@ static const char name_exynos4210[] = "EXYNOS4210"; static const char name_exynos4212[] = "EXYNOS4212"; static const char name_exynos4412[] = "EXYNOS4412"; +static void exynos4_map_io(void); +static void exynos4_init_clocks(int xtal); +static void exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no); +static int exynos_init(void); + static struct cpu_table cpu_ids[] __initdata = { { .idcode = EXYNOS4210_CPU_ID, @@ -225,7 +230,7 @@ void __init exynos_init_io(struct map_desc *mach_desc, int size) s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids)); } -void __init exynos4_map_io(void) +static void __init exynos4_map_io(void) { iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc)); @@ -256,7 +261,7 @@ void __init exynos4_map_io(void) s5p_hdmi_setname("exynos4-hdmi"); } -void __init exynos4_init_clocks(int xtal) +static void __init exynos4_init_clocks(int xtal) { printk(KERN_DEBUG "%s: initializing clocks\n", __func__); @@ -456,7 +461,7 @@ static int __init exynos4_l2x0_cache_init(void) early_initcall(exynos4_l2x0_cache_init); #endif -int __init exynos_init(void) +static int __init exynos_init(void) { printk(KERN_INFO "EXYNOS: Initializing architecture\n"); return device_register(&exynos4_dev); @@ -464,7 +469,7 @@ int __init exynos_init(void) /* uart registration process */ -void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no) +static void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no) { struct s3c2410_uartcfg *tcfg = cfg; u32 ucnt; diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 8c1efe6..b32c6b5 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -12,39 +12,33 @@ #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H #define __ARCH_ARM_MACH_EXYNOS_COMMON_H +extern struct sys_timer exynos4_timer; + void exynos_init_io(struct map_desc *mach_desc, int size); void exynos4_init_irq(void); +void exynos4_restart(char mode, const char *cmd); #ifdef CONFIG_ARCH_EXYNOS4 void exynos4_register_clocks(void); void exynos4_setup_clocks(void); -void exynos4210_register_clocks(void); -void exynos4212_register_clocks(void); - #else #define exynos4_register_clocks() #define exynos4_setup_clocks() - -#define exynos4210_register_clocks() -#define exynos4212_register_clocks() #endif -void exynos4_restart(char mode, const char *cmd); +#ifdef CONFIG_CPU_EXYNOS4210 +void exynos4210_register_clocks(void); -extern struct sys_timer exynos4_timer; +#else +#define exynos4210_register_clocks() +#endif -#ifdef CONFIG_ARCH_EXYNOS -extern int exynos_init(void); -extern void exynos4_map_io(void); -extern void exynos4_init_clocks(int xtal); -extern void exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no); +#ifdef CONFIG_SOC_EXYNOS4212 +void exynos4212_register_clocks(void); #else -#define exynos4_init_clocks NULL -#define exynos4_init_uarts NULL -#define exynos4_map_io NULL -#define exynos_init NULL +#define exynos4212_register_clocks() #endif #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */ -- cgit v0.10.2 From 920f4880162e70cb4fc8db8e7b0f15f3b307baf9 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Tue, 24 Jan 2012 20:52:52 +0900 Subject: ARM: EXYNOS: use exynos_init_uarts() instead of exynos4_init_uarts() Since exynos4_init_uarts() can be used for EXYNOS5 SoCs, this patch changes the name of function to exynos_init_uarts(). Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index a1f8a99..02eed29 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -52,7 +52,7 @@ static const char name_exynos4412[] = "EXYNOS4412"; static void exynos4_map_io(void); static void exynos4_init_clocks(int xtal); -static void exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no); +static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no); static int exynos_init(void); static struct cpu_table cpu_ids[] __initdata = { @@ -61,7 +61,7 @@ static struct cpu_table cpu_ids[] __initdata = { .idmask = EXYNOS4_CPU_MASK, .map_io = exynos4_map_io, .init_clocks = exynos4_init_clocks, - .init_uarts = exynos4_init_uarts, + .init_uarts = exynos_init_uarts, .init = exynos_init, .name = name_exynos4210, }, { @@ -69,7 +69,7 @@ static struct cpu_table cpu_ids[] __initdata = { .idmask = EXYNOS4_CPU_MASK, .map_io = exynos4_map_io, .init_clocks = exynos4_init_clocks, - .init_uarts = exynos4_init_uarts, + .init_uarts = exynos_init_uarts, .init = exynos_init, .name = name_exynos4212, }, { @@ -77,7 +77,7 @@ static struct cpu_table cpu_ids[] __initdata = { .idmask = EXYNOS4_CPU_MASK, .map_io = exynos4_map_io, .init_clocks = exynos4_init_clocks, - .init_uarts = exynos4_init_uarts, + .init_uarts = exynos_init_uarts, .init = exynos_init, .name = name_exynos4412, }, @@ -469,7 +469,7 @@ static int __init exynos_init(void) /* uart registration process */ -static void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no) +static void __init exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no) { struct s3c2410_uartcfg *tcfg = cfg; u32 ucnt; -- cgit v0.10.2 From 87b3c6ef1d7eb24c63cc3c7b7a424178aef410fc Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sun, 22 Jan 2012 21:46:13 +0900 Subject: ARM: EXYNOS: add clock part for EXYNOS5250 SoC This patch adds clock-exynos5.c for EXYNOS5250 now and that can be used for other EXYNOS5 SoCs later. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c new file mode 100644 index 0000000..d013982 --- /dev/null +++ b/arch/arm/mach-exynos/clock-exynos5.c @@ -0,0 +1,1247 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Clock support for EXYNOS5 SoCs + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "common.h" + +#ifdef CONFIG_PM_SLEEP +static struct sleep_save exynos5_clock_save[] = { + /* will be implemented */ +}; +#endif + +static struct clk exynos5_clk_sclk_dptxphy = { + .name = "sclk_dptx", +}; + +static struct clk exynos5_clk_sclk_hdmi24m = { + .name = "sclk_hdmi24m", + .rate = 24000000, +}; + +static struct clk exynos5_clk_sclk_hdmi27m = { + .name = "sclk_hdmi27m", + .rate = 27000000, +}; + +static struct clk exynos5_clk_sclk_hdmiphy = { + .name = "sclk_hdmiphy", +}; + +static struct clk exynos5_clk_sclk_usbphy = { + .name = "sclk_usbphy", + .rate = 48000000, +}; + +static int exynos5_clksrc_mask_top_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_TOP, clk, enable); +} + +static int exynos5_clksrc_mask_disp1_0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_DISP1_0, clk, enable); +} + +static int exynos5_clksrc_mask_fsys_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_FSYS, clk, enable); +} + +static int exynos5_clksrc_mask_gscl_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_GSCL, clk, enable); +} + +static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable); +} + +static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_CORE, clk, enable); +} + +static int exynos5_clk_ip_disp1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_DISP1, clk, enable); +} + +static int exynos5_clk_ip_fsys_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_FSYS, clk, enable); +} + +static int exynos5_clk_block_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_BLOCK, clk, enable); +} + +static int exynos5_clk_ip_gen_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GEN, clk, enable); +} + +static int exynos5_clk_ip_gps_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GPS, clk, enable); +} + +static int exynos5_clk_ip_mfc_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_MFC, clk, enable); +} + +static int exynos5_clk_ip_peric_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIC, clk, enable); +} + +static int exynos5_clk_ip_peris_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable); +} + +/* Core list of CMU_CPU side */ + +static struct clksrc_clk exynos5_clk_mout_apll = { + .clk = { + .name = "mout_apll", + }, + .sources = &clk_src_apll, + .reg_src = { .reg = EXYNOS5_CLKSRC_CPU, .shift = 0, .size = 1 }, +}; + +static struct clksrc_clk exynos5_clk_sclk_apll = { + .clk = { + .name = "sclk_apll", + .parent = &exynos5_clk_mout_apll.clk, + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 24, .size = 3 }, +}; + +static struct clksrc_clk exynos5_clk_mout_bpll = { + .clk = { + .name = "mout_bpll", + }, + .sources = &clk_src_bpll, + .reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 0, .size = 1 }, +}; + +static struct clk *exynos5_clk_src_bpll_user_list[] = { + [0] = &clk_fin_mpll, + [1] = &exynos5_clk_mout_bpll.clk, +}; + +static struct clksrc_sources exynos5_clk_src_bpll_user = { + .sources = exynos5_clk_src_bpll_user_list, + .nr_sources = ARRAY_SIZE(exynos5_clk_src_bpll_user_list), +}; + +static struct clksrc_clk exynos5_clk_mout_bpll_user = { + .clk = { + .name = "mout_bpll_user", + }, + .sources = &exynos5_clk_src_bpll_user, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 24, .size = 1 }, +}; + +static struct clksrc_clk exynos5_clk_mout_cpll = { + .clk = { + .name = "mout_cpll", + }, + .sources = &clk_src_cpll, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 8, .size = 1 }, +}; + +static struct clksrc_clk exynos5_clk_mout_epll = { + .clk = { + .name = "mout_epll", + }, + .sources = &clk_src_epll, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 12, .size = 1 }, +}; + +struct clksrc_clk exynos5_clk_mout_mpll = { + .clk = { + .name = "mout_mpll", + }, + .sources = &clk_src_mpll, + .reg_src = { .reg = EXYNOS5_CLKSRC_CORE1, .shift = 8, .size = 1 }, +}; + +static struct clk *exynos_clkset_vpllsrc_list[] = { + [0] = &clk_fin_vpll, + [1] = &exynos5_clk_sclk_hdmi27m, +}; + +static struct clksrc_sources exynos5_clkset_vpllsrc = { + .sources = exynos_clkset_vpllsrc_list, + .nr_sources = ARRAY_SIZE(exynos_clkset_vpllsrc_list), +}; + +static struct clksrc_clk exynos5_clk_vpllsrc = { + .clk = { + .name = "vpll_src", + .enable = exynos5_clksrc_mask_top_ctrl, + .ctrlbit = (1 << 0), + }, + .sources = &exynos5_clkset_vpllsrc, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 0, .size = 1 }, +}; + +static struct clk *exynos5_clkset_sclk_vpll_list[] = { + [0] = &exynos5_clk_vpllsrc.clk, + [1] = &clk_fout_vpll, +}; + +static struct clksrc_sources exynos5_clkset_sclk_vpll = { + .sources = exynos5_clkset_sclk_vpll_list, + .nr_sources = ARRAY_SIZE(exynos5_clkset_sclk_vpll_list), +}; + +static struct clksrc_clk exynos5_clk_sclk_vpll = { + .clk = { + .name = "sclk_vpll", + }, + .sources = &exynos5_clkset_sclk_vpll, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 16, .size = 1 }, +}; + +static struct clksrc_clk exynos5_clk_sclk_pixel = { + .clk = { + .name = "sclk_pixel", + .parent = &exynos5_clk_sclk_vpll.clk, + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 28, .size = 4 }, +}; + +static struct clk *exynos5_clkset_sclk_hdmi_list[] = { + [0] = &exynos5_clk_sclk_pixel.clk, + [1] = &exynos5_clk_sclk_hdmiphy, +}; + +static struct clksrc_sources exynos5_clkset_sclk_hdmi = { + .sources = exynos5_clkset_sclk_hdmi_list, + .nr_sources = ARRAY_SIZE(exynos5_clkset_sclk_hdmi_list), +}; + +static struct clksrc_clk exynos5_clk_sclk_hdmi = { + .clk = { + .name = "sclk_hdmi", + .enable = exynos5_clksrc_mask_disp1_0_ctrl, + .ctrlbit = (1 << 20), + }, + .sources = &exynos5_clkset_sclk_hdmi, + .reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 20, .size = 1 }, +}; + +static struct clksrc_clk *exynos5_sclk_tv[] = { + &exynos5_clk_sclk_pixel, + &exynos5_clk_sclk_hdmi, +}; + +static struct clk *exynos5_clk_src_mpll_user_list[] = { + [0] = &clk_fin_mpll, + [1] = &exynos5_clk_mout_mpll.clk, +}; + +static struct clksrc_sources exynos5_clk_src_mpll_user = { + .sources = exynos5_clk_src_mpll_user_list, + .nr_sources = ARRAY_SIZE(exynos5_clk_src_mpll_user_list), +}; + +static struct clksrc_clk exynos5_clk_mout_mpll_user = { + .clk = { + .name = "mout_mpll_user", + }, + .sources = &exynos5_clk_src_mpll_user, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 20, .size = 1 }, +}; + +static struct clk *exynos5_clkset_mout_cpu_list[] = { + [0] = &exynos5_clk_mout_apll.clk, + [1] = &exynos5_clk_mout_mpll.clk, +}; + +static struct clksrc_sources exynos5_clkset_mout_cpu = { + .sources = exynos5_clkset_mout_cpu_list, + .nr_sources = ARRAY_SIZE(exynos5_clkset_mout_cpu_list), +}; + +static struct clksrc_clk exynos5_clk_mout_cpu = { + .clk = { + .name = "mout_cpu", + }, + .sources = &exynos5_clkset_mout_cpu, + .reg_src = { .reg = EXYNOS5_CLKSRC_CPU, .shift = 16, .size = 1 }, +}; + +static struct clksrc_clk exynos5_clk_dout_armclk = { + .clk = { + .name = "dout_armclk", + .parent = &exynos5_clk_mout_cpu.clk, + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 0, .size = 3 }, +}; + +static struct clksrc_clk exynos5_clk_dout_arm2clk = { + .clk = { + .name = "dout_arm2clk", + .parent = &exynos5_clk_dout_armclk.clk, + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 28, .size = 3 }, +}; + +static struct clk exynos5_clk_armclk = { + .name = "armclk", + .parent = &exynos5_clk_dout_arm2clk.clk, +}; + +/* Core list of CMU_CDREX side */ + +static struct clk *exynos5_clkset_cdrex_list[] = { + [0] = &exynos5_clk_mout_mpll.clk, + [1] = &exynos5_clk_mout_bpll.clk, +}; + +static struct clksrc_sources exynos5_clkset_cdrex = { + .sources = exynos5_clkset_cdrex_list, + .nr_sources = ARRAY_SIZE(exynos5_clkset_cdrex_list), +}; + +static struct clksrc_clk exynos5_clk_cdrex = { + .clk = { + .name = "clk_cdrex", + }, + .sources = &exynos5_clkset_cdrex, + .reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 4, .size = 1 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_CDREX, .shift = 16, .size = 3 }, +}; + +static struct clksrc_clk exynos5_clk_aclk_acp = { + .clk = { + .name = "aclk_acp", + .parent = &exynos5_clk_mout_mpll.clk, + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_ACP, .shift = 0, .size = 3 }, +}; + +static struct clksrc_clk exynos5_clk_pclk_acp = { + .clk = { + .name = "pclk_acp", + .parent = &exynos5_clk_aclk_acp.clk, + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_ACP, .shift = 4, .size = 3 }, +}; + +/* Core list of CMU_TOP side */ + +struct clk *exynos5_clkset_aclk_top_list[] = { + [0] = &exynos5_clk_mout_mpll_user.clk, + [1] = &exynos5_clk_mout_bpll_user.clk, +}; + +struct clksrc_sources exynos5_clkset_aclk = { + .sources = exynos5_clkset_aclk_top_list, + .nr_sources = ARRAY_SIZE(exynos5_clkset_aclk_top_list), +}; + +static struct clksrc_clk exynos5_clk_aclk_400 = { + .clk = { + .name = "aclk_400", + }, + .sources = &exynos5_clkset_aclk, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 }, +}; + +struct clk *exynos5_clkset_aclk_333_166_list[] = { + [0] = &exynos5_clk_mout_cpll.clk, + [1] = &exynos5_clk_mout_mpll_user.clk, +}; + +struct clksrc_sources exynos5_clkset_aclk_333_166 = { + .sources = exynos5_clkset_aclk_333_166_list, + .nr_sources = ARRAY_SIZE(exynos5_clkset_aclk_333_166_list), +}; + +static struct clksrc_clk exynos5_clk_aclk_333 = { + .clk = { + .name = "aclk_333", + }, + .sources = &exynos5_clkset_aclk_333_166, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 16, .size = 1 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 20, .size = 3 }, +}; + +static struct clksrc_clk exynos5_clk_aclk_166 = { + .clk = { + .name = "aclk_166", + }, + .sources = &exynos5_clkset_aclk_333_166, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 8, .size = 1 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 8, .size = 3 }, +}; + +static struct clksrc_clk exynos5_clk_aclk_266 = { + .clk = { + .name = "aclk_266", + .parent = &exynos5_clk_mout_mpll_user.clk, + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 16, .size = 3 }, +}; + +static struct clksrc_clk exynos5_clk_aclk_200 = { + .clk = { + .name = "aclk_200", + }, + .sources = &exynos5_clkset_aclk, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 12, .size = 1 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 12, .size = 3 }, +}; + +static struct clksrc_clk exynos5_clk_aclk_66_pre = { + .clk = { + .name = "aclk_66_pre", + .parent = &exynos5_clk_mout_mpll_user.clk, + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_TOP1, .shift = 24, .size = 3 }, +}; + +static struct clksrc_clk exynos5_clk_aclk_66 = { + .clk = { + .name = "aclk_66", + .parent = &exynos5_clk_aclk_66_pre.clk, + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 0, .size = 3 }, +}; + +static struct clk exynos5_init_clocks_off[] = { + { + .name = "timers", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 24), + }, { + .name = "rtc", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peris_ctrl, + .ctrlbit = (1 << 20), + }, { + .name = "hsmmc", + .devname = "s3c-sdhci.0", + .parent = &exynos5_clk_aclk_200.clk, + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "hsmmc", + .devname = "s3c-sdhci.1", + .parent = &exynos5_clk_aclk_200.clk, + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 13), + }, { + .name = "hsmmc", + .devname = "s3c-sdhci.2", + .parent = &exynos5_clk_aclk_200.clk, + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 14), + }, { + .name = "hsmmc", + .devname = "s3c-sdhci.3", + .parent = &exynos5_clk_aclk_200.clk, + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 15), + }, { + .name = "dwmci", + .parent = &exynos5_clk_aclk_200.clk, + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 16), + }, { + .name = "sata", + .devname = "ahci", + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "sata_phy", + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 24), + }, { + .name = "sata_phy_i2c", + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 25), + }, { + .name = "mfc", + .devname = "s5p-mfc", + .enable = exynos5_clk_ip_mfc_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "hdmi", + .devname = "exynos4-hdmi", + .enable = exynos5_clk_ip_disp1_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "mixer", + .devname = "s5p-mixer", + .enable = exynos5_clk_ip_disp1_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "jpeg", + .enable = exynos5_clk_ip_gen_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "dsim0", + .enable = exynos5_clk_ip_disp1_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "iis", + .devname = "samsung-i2s.1", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 20), + }, { + .name = "iis", + .devname = "samsung-i2s.2", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 21), + }, { + .name = "pcm", + .devname = "samsung-pcm.1", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 22), + }, { + .name = "pcm", + .devname = "samsung-pcm.2", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 23), + }, { + .name = "spdif", + .devname = "samsung-spdif", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 26), + }, { + .name = "ac97", + .devname = "samsung-ac97", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 27), + }, { + .name = "usbhost", + .enable = exynos5_clk_ip_fsys_ctrl , + .ctrlbit = (1 << 18), + }, { + .name = "usbotg", + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "gps", + .enable = exynos5_clk_ip_gps_ctrl, + .ctrlbit = ((1 << 3) | (1 << 2) | (1 << 0)), + }, { + .name = "nfcon", + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 22), + }, { + .name = "iop", + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = ((1 << 30) | (1 << 26) | (1 << 23)), + }, { + .name = "core_iop", + .enable = exynos5_clk_ip_core_ctrl, + .ctrlbit = ((1 << 21) | (1 << 3)), + }, { + .name = "mcu_iop", + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "i2c", + .devname = "s3c2440-i2c.0", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "i2c", + .devname = "s3c2440-i2c.1", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "i2c", + .devname = "s3c2440-i2c.2", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "i2c", + .devname = "s3c2440-i2c.3", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 9), + }, { + .name = "i2c", + .devname = "s3c2440-i2c.4", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 10), + }, { + .name = "i2c", + .devname = "s3c2440-i2c.5", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 11), + }, { + .name = "i2c", + .devname = "s3c2440-i2c.6", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "i2c", + .devname = "s3c2440-i2c.7", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 13), + }, { + .name = "i2c", + .devname = "s3c2440-hdmiphy-i2c", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 14), + } +}; + +static struct clk exynos5_init_clocks_on[] = { + { + .name = "uart", + .devname = "s5pv210-uart.0", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "uart", + .devname = "s5pv210-uart.1", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "uart", + .devname = "s5pv210-uart.2", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "uart", + .devname = "s5pv210-uart.3", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "uart", + .devname = "s5pv210-uart.4", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "uart", + .devname = "s5pv210-uart.5", + .enable = exynos5_clk_ip_peric_ctrl, + .ctrlbit = (1 << 5), + } +}; + +static struct clk exynos5_clk_pdma0 = { + .name = "dma", + .devname = "dma-pl330.0", + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 1), +}; + +static struct clk exynos5_clk_pdma1 = { + .name = "dma", + .devname = "dma-pl330.1", + .enable = exynos5_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 1), +}; + +static struct clk exynos5_clk_mdma1 = { + .name = "dma", + .devname = "dma-pl330.2", + .enable = exynos5_clk_ip_gen_ctrl, + .ctrlbit = (1 << 4), +}; + +struct clk *exynos5_clkset_group_list[] = { + [0] = &clk_ext_xtal_mux, + [1] = NULL, + [2] = &exynos5_clk_sclk_hdmi24m, + [3] = &exynos5_clk_sclk_dptxphy, + [4] = &exynos5_clk_sclk_usbphy, + [5] = &exynos5_clk_sclk_hdmiphy, + [6] = &exynos5_clk_mout_mpll_user.clk, + [7] = &exynos5_clk_mout_epll.clk, + [8] = &exynos5_clk_sclk_vpll.clk, + [9] = &exynos5_clk_mout_cpll.clk, +}; + +struct clksrc_sources exynos5_clkset_group = { + .sources = exynos5_clkset_group_list, + .nr_sources = ARRAY_SIZE(exynos5_clkset_group_list), +}; + +/* Possible clock sources for aclk_266_gscl_sub Mux */ +static struct clk *clk_src_gscl_266_list[] = { + [0] = &clk_ext_xtal_mux, + [1] = &exynos5_clk_aclk_266.clk, +}; + +static struct clksrc_sources clk_src_gscl_266 = { + .sources = clk_src_gscl_266_list, + .nr_sources = ARRAY_SIZE(clk_src_gscl_266_list), +}; + +static struct clksrc_clk exynos5_clk_dout_mmc0 = { + .clk = { + .name = "dout_mmc0", + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 0, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk exynos5_clk_dout_mmc1 = { + .clk = { + .name = "dout_mmc1", + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 4, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 16, .size = 4 }, +}; + +static struct clksrc_clk exynos5_clk_dout_mmc2 = { + .clk = { + .name = "dout_mmc2", + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 8, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk exynos5_clk_dout_mmc3 = { + .clk = { + .name = "dout_mmc3", + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 12, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 16, .size = 4 }, +}; + +static struct clksrc_clk exynos5_clk_dout_mmc4 = { + .clk = { + .name = "dout_mmc4", + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 16, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS3, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk exynos5_clk_sclk_uart0 = { + .clk = { + .name = "uclk1", + .devname = "exynos4210-uart.0", + .enable = exynos5_clksrc_mask_peric0_ctrl, + .ctrlbit = (1 << 0), + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 0, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk exynos5_clk_sclk_uart1 = { + .clk = { + .name = "uclk1", + .devname = "exynos4210-uart.1", + .enable = exynos5_clksrc_mask_peric0_ctrl, + .ctrlbit = (1 << 4), + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 4, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 4, .size = 4 }, +}; + +static struct clksrc_clk exynos5_clk_sclk_uart2 = { + .clk = { + .name = "uclk1", + .devname = "exynos4210-uart.2", + .enable = exynos5_clksrc_mask_peric0_ctrl, + .ctrlbit = (1 << 8), + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 8, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk exynos5_clk_sclk_uart3 = { + .clk = { + .name = "uclk1", + .devname = "exynos4210-uart.3", + .enable = exynos5_clksrc_mask_peric0_ctrl, + .ctrlbit = (1 << 12), + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 12, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 12, .size = 4 }, +}; + +static struct clksrc_clk exynos5_clk_sclk_mmc0 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.0", + .parent = &exynos5_clk_dout_mmc0.clk, + .enable = exynos5_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 0), + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 8, .size = 8 }, +}; + +static struct clksrc_clk exynos5_clk_sclk_mmc1 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.1", + .parent = &exynos5_clk_dout_mmc1.clk, + .enable = exynos5_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 4), + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 24, .size = 8 }, +}; + +static struct clksrc_clk exynos5_clk_sclk_mmc2 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.2", + .parent = &exynos5_clk_dout_mmc2.clk, + .enable = exynos5_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 8), + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 8, .size = 8 }, +}; + +static struct clksrc_clk exynos5_clk_sclk_mmc3 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.3", + .parent = &exynos5_clk_dout_mmc3.clk, + .enable = exynos5_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 12), + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 24, .size = 8 }, +}; + +static struct clksrc_clk exynos5_clksrcs[] = { + { + .clk = { + .name = "sclk_dwmci", + .parent = &exynos5_clk_dout_mmc4.clk, + .enable = exynos5_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 16), + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS3, .shift = 8, .size = 8 }, + }, { + .clk = { + .name = "sclk_fimd", + .devname = "s3cfb.1", + .enable = exynos5_clksrc_mask_disp1_0_ctrl, + .ctrlbit = (1 << 0), + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 0, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "aclk_266_gscl", + }, + .sources = &clk_src_gscl_266, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP3, .shift = 8, .size = 1 }, + }, { + .clk = { + .name = "sclk_g3d", + .devname = "mali-t604.0", + .enable = exynos5_clk_block_ctrl, + .ctrlbit = (1 << 1), + }, + .sources = &exynos5_clkset_aclk, + .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 }, + }, { + .clk = { + .name = "sclk_gscl_wrap", + .devname = "s5p-mipi-csis.0", + .enable = exynos5_clksrc_mask_gscl_ctrl, + .ctrlbit = (1 << 24), + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 24, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 24, .size = 4 }, + }, { + .clk = { + .name = "sclk_gscl_wrap", + .devname = "s5p-mipi-csis.1", + .enable = exynos5_clksrc_mask_gscl_ctrl, + .ctrlbit = (1 << 28), + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 28, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 28, .size = 4 }, + }, { + .clk = { + .name = "sclk_cam0", + .enable = exynos5_clksrc_mask_gscl_ctrl, + .ctrlbit = (1 << 16), + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 16, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_cam1", + .enable = exynos5_clksrc_mask_gscl_ctrl, + .ctrlbit = (1 << 20), + }, + .sources = &exynos5_clkset_group, + .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 20, .size = 4 }, + .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_jpeg", + .parent = &exynos5_clk_mout_cpll.clk, + }, + .reg_div = { .reg = EXYNOS5_CLKDIV_GEN, .shift = 4, .size = 3 }, + }, +}; + +/* Clock initialization code */ +static struct clksrc_clk *exynos5_sysclks[] = { + &exynos5_clk_mout_apll, + &exynos5_clk_sclk_apll, + &exynos5_clk_mout_bpll, + &exynos5_clk_mout_bpll_user, + &exynos5_clk_mout_cpll, + &exynos5_clk_mout_epll, + &exynos5_clk_mout_mpll, + &exynos5_clk_mout_mpll_user, + &exynos5_clk_vpllsrc, + &exynos5_clk_sclk_vpll, + &exynos5_clk_mout_cpu, + &exynos5_clk_dout_armclk, + &exynos5_clk_dout_arm2clk, + &exynos5_clk_cdrex, + &exynos5_clk_aclk_400, + &exynos5_clk_aclk_333, + &exynos5_clk_aclk_266, + &exynos5_clk_aclk_200, + &exynos5_clk_aclk_166, + &exynos5_clk_aclk_66_pre, + &exynos5_clk_aclk_66, + &exynos5_clk_dout_mmc0, + &exynos5_clk_dout_mmc1, + &exynos5_clk_dout_mmc2, + &exynos5_clk_dout_mmc3, + &exynos5_clk_dout_mmc4, + &exynos5_clk_aclk_acp, + &exynos5_clk_pclk_acp, +}; + +static struct clk *exynos5_clk_cdev[] = { + &exynos5_clk_pdma0, + &exynos5_clk_pdma1, + &exynos5_clk_mdma1, +}; + +static struct clksrc_clk *exynos5_clksrc_cdev[] = { + &exynos5_clk_sclk_uart0, + &exynos5_clk_sclk_uart1, + &exynos5_clk_sclk_uart2, + &exynos5_clk_sclk_uart3, + &exynos5_clk_sclk_mmc0, + &exynos5_clk_sclk_mmc1, + &exynos5_clk_sclk_mmc2, + &exynos5_clk_sclk_mmc3, +}; + +static struct clk_lookup exynos5_clk_lookup[] = { + CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos5_clk_sclk_uart0.clk), + CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos5_clk_sclk_uart1.clk), + CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos5_clk_sclk_uart2.clk), + CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos5_clk_sclk_uart3.clk), + CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &exynos5_clk_sclk_mmc0.clk), + CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk), + CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk), + CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk), + CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos5_clk_pdma0), + CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1), + CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1), +}; + +static unsigned long exynos5_epll_get_rate(struct clk *clk) +{ + return clk->rate; +} + +static struct clk *exynos5_clks[] __initdata = { + &exynos5_clk_sclk_hdmi27m, + &exynos5_clk_sclk_hdmiphy, + &clk_fout_bpll, + &clk_fout_cpll, + &exynos5_clk_armclk, +}; + +static u32 epll_div[][6] = { + { 192000000, 0, 48, 3, 1, 0 }, + { 180000000, 0, 45, 3, 1, 0 }, + { 73728000, 1, 73, 3, 3, 47710 }, + { 67737600, 1, 90, 4, 3, 20762 }, + { 49152000, 0, 49, 3, 3, 9961 }, + { 45158400, 0, 45, 3, 3, 10381 }, + { 180633600, 0, 45, 3, 1, 10381 }, +}; + +static int exynos5_epll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int epll_con, epll_con_k; + unsigned int i; + unsigned int tmp; + unsigned int epll_rate; + unsigned int locktime; + unsigned int lockcnt; + + /* Return if nothing changed */ + if (clk->rate == rate) + return 0; + + if (clk->parent) + epll_rate = clk_get_rate(clk->parent); + else + epll_rate = clk_ext_xtal_mux.rate; + + if (epll_rate != 24000000) { + pr_err("Invalid Clock : recommended clock is 24MHz.\n"); + return -EINVAL; + } + + epll_con = __raw_readl(EXYNOS5_EPLL_CON0); + epll_con &= ~(0x1 << 27 | \ + PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \ + PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \ + PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT); + + for (i = 0; i < ARRAY_SIZE(epll_div); i++) { + if (epll_div[i][0] == rate) { + epll_con_k = epll_div[i][5] << 0; + epll_con |= epll_div[i][1] << 27; + epll_con |= epll_div[i][2] << PLL46XX_MDIV_SHIFT; + epll_con |= epll_div[i][3] << PLL46XX_PDIV_SHIFT; + epll_con |= epll_div[i][4] << PLL46XX_SDIV_SHIFT; + break; + } + } + + if (i == ARRAY_SIZE(epll_div)) { + printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", + __func__); + return -EINVAL; + } + + epll_rate /= 1000000; + + /* 3000 max_cycls : specification data */ + locktime = 3000 / epll_rate * epll_div[i][3]; + lockcnt = locktime * 10000 / (10000 / epll_rate); + + __raw_writel(lockcnt, EXYNOS5_EPLL_LOCK); + + __raw_writel(epll_con, EXYNOS5_EPLL_CON0); + __raw_writel(epll_con_k, EXYNOS5_EPLL_CON1); + + do { + tmp = __raw_readl(EXYNOS5_EPLL_CON0); + } while (!(tmp & 0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT)); + + clk->rate = rate; + + return 0; +} + +static struct clk_ops exynos5_epll_ops = { + .get_rate = exynos5_epll_get_rate, + .set_rate = exynos5_epll_set_rate, +}; + +static int xtal_rate; + +static unsigned long exynos5_fout_apll_get_rate(struct clk *clk) +{ + return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS5_APLL_CON0)); +} + +static struct clk_ops exynos5_fout_apll_ops = { + .get_rate = exynos5_fout_apll_get_rate, +}; + +#ifdef CONFIG_PM +static int exynos5_clock_suspend(void) +{ + s3c_pm_do_save(exynos5_clock_save, ARRAY_SIZE(exynos5_clock_save)); + + return 0; +} + +static void exynos5_clock_resume(void) +{ + s3c_pm_do_restore_core(exynos5_clock_save, ARRAY_SIZE(exynos5_clock_save)); +} +#else +#define exynos5_clock_suspend NULL +#define exynos5_clock_resume NULL +#endif + +struct syscore_ops exynos5_clock_syscore_ops = { + .suspend = exynos5_clock_suspend, + .resume = exynos5_clock_resume, +}; + +void __init_or_cpufreq exynos5_setup_clocks(void) +{ + struct clk *xtal_clk; + unsigned long apll; + unsigned long bpll; + unsigned long cpll; + unsigned long mpll; + unsigned long epll; + unsigned long vpll; + unsigned long vpllsrc; + unsigned long xtal; + unsigned long armclk; + unsigned long mout_cdrex; + unsigned long aclk_400; + unsigned long aclk_333; + unsigned long aclk_266; + unsigned long aclk_200; + unsigned long aclk_166; + unsigned long aclk_66; + unsigned int ptr; + + printk(KERN_DEBUG "%s: registering clocks\n", __func__); + + xtal_clk = clk_get(NULL, "xtal"); + BUG_ON(IS_ERR(xtal_clk)); + + xtal = clk_get_rate(xtal_clk); + + xtal_rate = xtal; + + clk_put(xtal_clk); + + printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal); + + apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_APLL_CON0)); + bpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_BPLL_CON0)); + cpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_CPLL_CON0)); + mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_MPLL_CON0)); + epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS5_EPLL_CON0), + __raw_readl(EXYNOS5_EPLL_CON1)); + + vpllsrc = clk_get_rate(&exynos5_clk_vpllsrc.clk); + vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS5_VPLL_CON0), + __raw_readl(EXYNOS5_VPLL_CON1)); + + clk_fout_apll.ops = &exynos5_fout_apll_ops; + clk_fout_bpll.rate = bpll; + clk_fout_cpll.rate = cpll; + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + clk_fout_vpll.rate = vpll; + + printk(KERN_INFO "EXYNOS5: PLL settings, A=%ld, B=%ld, C=%ld\n" + "M=%ld, E=%ld V=%ld", + apll, bpll, cpll, mpll, epll, vpll); + + armclk = clk_get_rate(&exynos5_clk_armclk); + mout_cdrex = clk_get_rate(&exynos5_clk_cdrex.clk); + + aclk_400 = clk_get_rate(&exynos5_clk_aclk_400.clk); + aclk_333 = clk_get_rate(&exynos5_clk_aclk_333.clk); + aclk_266 = clk_get_rate(&exynos5_clk_aclk_266.clk); + aclk_200 = clk_get_rate(&exynos5_clk_aclk_200.clk); + aclk_166 = clk_get_rate(&exynos5_clk_aclk_166.clk); + aclk_66 = clk_get_rate(&exynos5_clk_aclk_66.clk); + + printk(KERN_INFO "EXYNOS5: ARMCLK=%ld, CDREX=%ld, ACLK400=%ld\n" + "ACLK333=%ld, ACLK266=%ld, ACLK200=%ld\n" + "ACLK166=%ld, ACLK66=%ld\n", + armclk, mout_cdrex, aclk_400, + aclk_333, aclk_266, aclk_200, + aclk_166, aclk_66); + + + clk_fout_epll.ops = &exynos5_epll_ops; + + if (clk_set_parent(&exynos5_clk_mout_epll.clk, &clk_fout_epll)) + printk(KERN_ERR "Unable to set parent %s of clock %s.\n", + clk_fout_epll.name, exynos5_clk_mout_epll.clk.name); + + clk_set_rate(&exynos5_clk_sclk_apll.clk, 100000000); + clk_set_rate(&exynos5_clk_aclk_266.clk, 300000000); + + clk_set_rate(&exynos5_clk_aclk_acp.clk, 267000000); + clk_set_rate(&exynos5_clk_pclk_acp.clk, 134000000); + + for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clksrcs); ptr++) + s3c_set_clksrc(&exynos5_clksrcs[ptr], true); +} + +void __init exynos5_register_clocks(void) +{ + int ptr; + + s3c24xx_register_clocks(exynos5_clks, ARRAY_SIZE(exynos5_clks)); + + for (ptr = 0; ptr < ARRAY_SIZE(exynos5_sysclks); ptr++) + s3c_register_clksrc(exynos5_sysclks[ptr], 1); + + for (ptr = 0; ptr < ARRAY_SIZE(exynos5_sclk_tv); ptr++) + s3c_register_clksrc(exynos5_sclk_tv[ptr], 1); + + for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clksrc_cdev); ptr++) + s3c_register_clksrc(exynos5_clksrc_cdev[ptr], 1); + + s3c_register_clksrc(exynos5_clksrcs, ARRAY_SIZE(exynos5_clksrcs)); + s3c_register_clocks(exynos5_init_clocks_on, ARRAY_SIZE(exynos5_init_clocks_on)); + + s3c24xx_register_clocks(exynos5_clk_cdev, ARRAY_SIZE(exynos5_clk_cdev)); + for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clk_cdev); ptr++) + s3c_disable_clocks(exynos5_clk_cdev[ptr], 1); + + s3c_register_clocks(exynos5_init_clocks_off, ARRAY_SIZE(exynos5_init_clocks_off)); + s3c_disable_clocks(exynos5_init_clocks_off, ARRAY_SIZE(exynos5_init_clocks_off)); + clkdev_add_table(exynos5_clk_lookup, ARRAY_SIZE(exynos5_clk_lookup)); + + register_syscore_ops(&exynos5_clock_syscore_ops); + s3c_pwmclk_init(); +} diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h index 1e4abd6..e141c1f 100644 --- a/arch/arm/mach-exynos/include/mach/regs-clock.h +++ b/arch/arm/mach-exynos/include/mach/regs-clock.h @@ -253,6 +253,68 @@ #define EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT (0) #define EXYNOS4_CLKDIV_CAM1_JPEG_MASK (0xf << EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT) +/* For EXYNOS5250 */ + +#define EXYNOS5_APLL_CON0 EXYNOS_CLKREG(0x00100) +#define EXYNOS5_CLKSRC_CPU EXYNOS_CLKREG(0x00200) +#define EXYNOS5_CLKDIV_CPU0 EXYNOS_CLKREG(0x00500) +#define EXYNOS5_MPLL_CON0 EXYNOS_CLKREG(0x04100) +#define EXYNOS5_CLKSRC_CORE1 EXYNOS_CLKREG(0x04204) + +#define EXYNOS5_CLKGATE_IP_CORE EXYNOS_CLKREG(0x04900) + +#define EXYNOS5_CLKDIV_ACP EXYNOS_CLKREG(0x08500) + +#define EXYNOS5_CLKSRC_TOP2 EXYNOS_CLKREG(0x10218) +#define EXYNOS5_EPLL_CON0 EXYNOS_CLKREG(0x10130) +#define EXYNOS5_EPLL_CON1 EXYNOS_CLKREG(0x10134) +#define EXYNOS5_VPLL_CON0 EXYNOS_CLKREG(0x10140) +#define EXYNOS5_VPLL_CON1 EXYNOS_CLKREG(0x10144) +#define EXYNOS5_CPLL_CON0 EXYNOS_CLKREG(0x10120) + +#define EXYNOS5_CLKSRC_TOP0 EXYNOS_CLKREG(0x10210) +#define EXYNOS5_CLKSRC_TOP3 EXYNOS_CLKREG(0x1021C) +#define EXYNOS5_CLKSRC_GSCL EXYNOS_CLKREG(0x10220) +#define EXYNOS5_CLKSRC_DISP1_0 EXYNOS_CLKREG(0x1022C) +#define EXYNOS5_CLKSRC_FSYS EXYNOS_CLKREG(0x10244) +#define EXYNOS5_CLKSRC_PERIC0 EXYNOS_CLKREG(0x10250) + +#define EXYNOS5_CLKSRC_MASK_TOP EXYNOS_CLKREG(0x10310) +#define EXYNOS5_CLKSRC_MASK_GSCL EXYNOS_CLKREG(0x10320) +#define EXYNOS5_CLKSRC_MASK_DISP1_0 EXYNOS_CLKREG(0x1032C) +#define EXYNOS5_CLKSRC_MASK_FSYS EXYNOS_CLKREG(0x10340) +#define EXYNOS5_CLKSRC_MASK_PERIC0 EXYNOS_CLKREG(0x10350) + +#define EXYNOS5_CLKDIV_TOP0 EXYNOS_CLKREG(0x10510) +#define EXYNOS5_CLKDIV_TOP1 EXYNOS_CLKREG(0x10514) +#define EXYNOS5_CLKDIV_GSCL EXYNOS_CLKREG(0x10520) +#define EXYNOS5_CLKDIV_DISP1_0 EXYNOS_CLKREG(0x1052C) +#define EXYNOS5_CLKDIV_GEN EXYNOS_CLKREG(0x1053C) +#define EXYNOS5_CLKDIV_FSYS0 EXYNOS_CLKREG(0x10548) +#define EXYNOS5_CLKDIV_FSYS1 EXYNOS_CLKREG(0x1054C) +#define EXYNOS5_CLKDIV_FSYS2 EXYNOS_CLKREG(0x10550) +#define EXYNOS5_CLKDIV_FSYS3 EXYNOS_CLKREG(0x10554) +#define EXYNOS5_CLKDIV_PERIC0 EXYNOS_CLKREG(0x10558) + +#define EXYNOS5_CLKGATE_IP_ACP EXYNOS_CLKREG(0x08800) +#define EXYNOS5_CLKGATE_IP_GSCL EXYNOS_CLKREG(0x10920) +#define EXYNOS5_CLKGATE_IP_DISP1 EXYNOS_CLKREG(0x10928) +#define EXYNOS5_CLKGATE_IP_MFC EXYNOS_CLKREG(0x1092C) +#define EXYNOS5_CLKGATE_IP_GEN EXYNOS_CLKREG(0x10934) +#define EXYNOS5_CLKGATE_IP_FSYS EXYNOS_CLKREG(0x10944) +#define EXYNOS5_CLKGATE_IP_GPS EXYNOS_CLKREG(0x1094C) +#define EXYNOS5_CLKGATE_IP_PERIC EXYNOS_CLKREG(0x10950) +#define EXYNOS5_CLKGATE_IP_PERIS EXYNOS_CLKREG(0x10960) +#define EXYNOS5_CLKGATE_BLOCK EXYNOS_CLKREG(0x10980) + +#define EXYNOS5_BPLL_CON0 EXYNOS_CLKREG(0x20110) +#define EXYNOS5_CLKSRC_CDREX EXYNOS_CLKREG(0x20200) +#define EXYNOS5_CLKDIV_CDREX EXYNOS_CLKREG(0x20500) + +#define EXYNOS5_EPLL_LOCK EXYNOS_CLKREG(0x10030) + +#define EXYNOS5_EPLLCON0_LOCKED_SHIFT (29) + /* Compatibility defines and inclusion */ #include diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c index 963edea..f68a9bb 100644 --- a/arch/arm/plat-s5p/clock.c +++ b/arch/arm/plat-s5p/clock.c @@ -61,6 +61,20 @@ struct clk clk_fout_apll = { .id = -1, }; +/* BPLL clock output */ + +struct clk clk_fout_bpll = { + .name = "fout_bpll", + .id = -1, +}; + +/* CPLL clock output */ + +struct clk clk_fout_cpll = { + .name = "fout_cpll", + .id = -1, +}; + /* MPLL clock output * No need .ctrlbit, this is always on */ @@ -101,6 +115,28 @@ struct clksrc_sources clk_src_apll = { .nr_sources = ARRAY_SIZE(clk_src_apll_list), }; +/* Possible clock sources for BPLL Mux */ +static struct clk *clk_src_bpll_list[] = { + [0] = &clk_fin_bpll, + [1] = &clk_fout_bpll, +}; + +struct clksrc_sources clk_src_bpll = { + .sources = clk_src_bpll_list, + .nr_sources = ARRAY_SIZE(clk_src_bpll_list), +}; + +/* Possible clock sources for CPLL Mux */ +static struct clk *clk_src_cpll_list[] = { + [0] = &clk_fin_cpll, + [1] = &clk_fout_cpll, +}; + +struct clksrc_sources clk_src_cpll = { + .sources = clk_src_cpll_list, + .nr_sources = ARRAY_SIZE(clk_src_cpll_list), +}; + /* Possible clock sources for MPLL Mux */ static struct clk *clk_src_mpll_list[] = { [0] = &clk_fin_mpll, diff --git a/arch/arm/plat-samsung/include/plat/s5p-clock.h b/arch/arm/plat-samsung/include/plat/s5p-clock.h index 984bf9e..1de4b32 100644 --- a/arch/arm/plat-samsung/include/plat/s5p-clock.h +++ b/arch/arm/plat-samsung/include/plat/s5p-clock.h @@ -18,6 +18,8 @@ #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) #define clk_fin_apll clk_ext_xtal_mux +#define clk_fin_bpll clk_ext_xtal_mux +#define clk_fin_cpll clk_ext_xtal_mux #define clk_fin_mpll clk_ext_xtal_mux #define clk_fin_epll clk_ext_xtal_mux #define clk_fin_dpll clk_ext_xtal_mux @@ -29,6 +31,8 @@ extern struct clk clk_xusbxti; extern struct clk clk_48m; extern struct clk s5p_clk_27m; extern struct clk clk_fout_apll; +extern struct clk clk_fout_bpll; +extern struct clk clk_fout_cpll; extern struct clk clk_fout_mpll; extern struct clk clk_fout_epll; extern struct clk clk_fout_dpll; @@ -37,6 +41,8 @@ extern struct clk clk_arm; extern struct clk clk_vpll; extern struct clksrc_sources clk_src_apll; +extern struct clksrc_sources clk_src_bpll; +extern struct clksrc_sources clk_src_cpll; extern struct clksrc_sources clk_src_mpll; extern struct clksrc_sources clk_src_epll; extern struct clksrc_sources clk_src_dpll; -- cgit v0.10.2 From b67545fd9b5335c38c028e7984a1bef9e789c8dc Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sat, 11 Feb 2012 22:11:14 +0900 Subject: ARM: EXYNOS: add initial setup-i2c0 for EXYNOS5 In all of Samsung platform, the setup-i2c0.c file for I2C channel 0 is always compiled. So when supporting new SoC,it should be updated for it. Since EXYNOS5 GPIO will be supported after this, there is no setup gpio in there now. It will be implemented with that, of course. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 995e7cc..2117f02 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -52,7 +52,7 @@ obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o -obj-$(CONFIG_ARCH_EXYNOS4) += setup-i2c0.o +obj-$(CONFIG_ARCH_EXYNOS) += setup-i2c0.o obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o obj-$(CONFIG_EXYNOS4_SETUP_FIMD0) += setup-fimd0.o obj-$(CONFIG_EXYNOS4_SETUP_I2C1) += setup-i2c1.o diff --git a/arch/arm/mach-exynos/setup-i2c0.c b/arch/arm/mach-exynos/setup-i2c0.c index d395bd1..b90d94c 100644 --- a/arch/arm/mach-exynos/setup-i2c0.c +++ b/arch/arm/mach-exynos/setup-i2c0.c @@ -1,7 +1,5 @@ /* - * linux/arch/arm/mach-exynos4/setup-i2c0.c - * - * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * Copyright (c) 2009-2012 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * * I2C0 GPIO configuration. @@ -18,9 +16,14 @@ struct platform_device; /* don't need the contents */ #include #include #include +#include void s3c_i2c0_cfg_gpio(struct platform_device *dev) { + if (soc_is_exynos5250()) + /* will be implemented with gpio function */ + return; + s3c_gpio_cfgall_range(EXYNOS4_GPD1(0), 2, S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); } -- cgit v0.10.2 From 171c067c1a3f903fca78f2610794441a7d1e64f3 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Fri, 10 Feb 2012 11:57:53 +0900 Subject: ARM: EXYNOS: add support uart for EXYNOS4 and EXYNOS5 Actually, the base address of uart is different between EXYNOS4 and EXYNOS5 and this patch enables to support uart for EXYNOS4 and EXYNOS5 SoCs at runtime. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 2117f02..f8a3770 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o # device support +obj-y += dev-uart.o obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o obj-$(CONFIG_EXYNOS4_DEV_PD) += dev-pd.o diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 02eed29..4a82cf0 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -477,7 +477,10 @@ static void __init exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no) for (ucnt = 0; ucnt < no; ucnt++, tcfg++) tcfg->has_fracval = 1; - s3c24xx_init_uartdevs("exynos4210-uart", s5p_uart_resources, cfg, no); + if (soc_is_exynos5250()) + s3c24xx_init_uartdevs("exynos4210-uart", exynos5_uart_resources, cfg, no); + else + s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no); } static DEFINE_SPINLOCK(eint_lock); diff --git a/arch/arm/mach-exynos/dev-uart.c b/arch/arm/mach-exynos/dev-uart.c new file mode 100644 index 0000000..2e85c02 --- /dev/null +++ b/arch/arm/mach-exynos/dev-uart.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Base EXYNOS UART resource and device definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define EXYNOS_UART_RESOURCE(_series, _nr) \ +static struct resource exynos##_series##_uart##_nr##_resource[] = { \ + [0] = DEFINE_RES_MEM(EXYNOS##_series##_PA_UART##_nr, EXYNOS##_series##_SZ_UART), \ + [1] = DEFINE_RES_IRQ(EXYNOS##_series##_IRQ_UART##_nr), \ +}; + +EXYNOS_UART_RESOURCE(4, 0) +EXYNOS_UART_RESOURCE(4, 1) +EXYNOS_UART_RESOURCE(4, 2) +EXYNOS_UART_RESOURCE(4, 3) + +struct s3c24xx_uart_resources exynos4_uart_resources[] __initdata = { + [0] = { + .resources = exynos4_uart0_resource, + .nr_resources = ARRAY_SIZE(exynos4_uart0_resource), + }, + [1] = { + .resources = exynos4_uart1_resource, + .nr_resources = ARRAY_SIZE(exynos4_uart1_resource), + }, + [2] = { + .resources = exynos4_uart2_resource, + .nr_resources = ARRAY_SIZE(exynos4_uart2_resource), + }, + [3] = { + .resources = exynos4_uart3_resource, + .nr_resources = ARRAY_SIZE(exynos4_uart3_resource), + }, +}; + +EXYNOS_UART_RESOURCE(5, 0) +EXYNOS_UART_RESOURCE(5, 1) +EXYNOS_UART_RESOURCE(5, 2) +EXYNOS_UART_RESOURCE(5, 3) + +struct s3c24xx_uart_resources exynos5_uart_resources[] __initdata = { + [0] = { + .resources = exynos5_uart0_resource, + .nr_resources = ARRAY_SIZE(exynos5_uart0_resource), + }, + [1] = { + .resources = exynos5_uart1_resource, + .nr_resources = ARRAY_SIZE(exynos5_uart0_resource), + }, + [2] = { + .resources = exynos5_uart2_resource, + .nr_resources = ARRAY_SIZE(exynos5_uart2_resource), + }, + [3] = { + .resources = exynos5_uart3_resource, + .nr_resources = ARRAY_SIZE(exynos5_uart3_resource), + }, +}; diff --git a/arch/arm/mach-exynos/include/mach/debug-macro.S b/arch/arm/mach-exynos/include/mach/debug-macro.S index 6cacf16..6c857ff 100644 --- a/arch/arm/mach-exynos/include/mach/debug-macro.S +++ b/arch/arm/mach-exynos/include/mach/debug-macro.S @@ -21,8 +21,13 @@ */ .macro addruart, rp, rv, tmp - ldr \rp, = S3C_PA_UART - ldr \rv, = S3C_VA_UART + mov \rp, #0x10000000 + ldr \rp, [\rp, #0x0] + and \rp, \rp, #0xf00000 + teq \rp, #0x500000 @@ EXYNOS5 + ldreq \rp, =EXYNOS5_PA_UART + movne \rp, #EXYNOS4_PA_UART @@ EXYNOS4 + ldr \rv, =S3C_VA_UART #if CONFIG_DEBUG_S3C_UART != 0 add \rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART) add \rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART) diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index 1d401c9..f78070e 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h @@ -173,4 +173,16 @@ /* Set the default NR_IRQS */ #define NR_IRQS (IRQ_TIMER_BASE + IRQ_TIMER_COUNT) +#define EXYNOS4_IRQ_UART0 IRQ_SPI(52) +#define EXYNOS4_IRQ_UART1 IRQ_SPI(53) +#define EXYNOS4_IRQ_UART2 IRQ_SPI(54) +#define EXYNOS4_IRQ_UART3 IRQ_SPI(55) +#define EXYNOS4_IRQ_UART4 IRQ_SPI(56) + +#define EXYNOS5_IRQ_UART0 IRQ_SPI(51) +#define EXYNOS5_IRQ_UART1 IRQ_SPI(52) +#define EXYNOS5_IRQ_UART2 IRQ_SPI(53) +#define EXYNOS5_IRQ_UART3 IRQ_SPI(54) +#define EXYNOS5_IRQ_UART4 IRQ_SPI(55) + #endif /* __ASM_ARCH_IRQS_H */ diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 2ad4e9c..ea513c6 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -153,7 +153,6 @@ #define S3C_PA_IIC7 EXYNOS4_PA_IIC(7) #define S3C_PA_RTC EXYNOS4_PA_RTC #define S3C_PA_WDT EXYNOS4_PA_WATCHDOG -#define S3C_PA_UART EXYNOS4_PA_UART #define S3C_PA_SPI0 EXYNOS4_PA_SPI0 #define S3C_PA_SPI1 EXYNOS4_PA_SPI1 #define S3C_PA_SPI2 EXYNOS4_PA_SPI2 @@ -182,15 +181,18 @@ /* Compatibility UART */ -#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) +#define EXYNOS4_PA_UART0 0x13800000 +#define EXYNOS4_PA_UART1 0x13810000 +#define EXYNOS4_PA_UART2 0x13820000 +#define EXYNOS4_PA_UART3 0x13830000 +#define EXYNOS4_SZ_UART SZ_256 -#define S5P_PA_UART(x) (EXYNOS4_PA_UART + ((x) * S3C_UART_OFFSET)) -#define S5P_PA_UART0 S5P_PA_UART(0) -#define S5P_PA_UART1 S5P_PA_UART(1) -#define S5P_PA_UART2 S5P_PA_UART(2) -#define S5P_PA_UART3 S5P_PA_UART(3) -#define S5P_PA_UART4 S5P_PA_UART(4) +#define EXYNOS5_PA_UART0 0x12C00000 +#define EXYNOS5_PA_UART1 0x12C10000 +#define EXYNOS5_PA_UART2 0x12C20000 +#define EXYNOS5_PA_UART3 0x12C30000 +#define EXYNOS5_SZ_UART SZ_256 -#define S5P_SZ_UART SZ_256 +#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-exynos/include/mach/uncompress.h b/arch/arm/mach-exynos/include/mach/uncompress.h index 21d97bc..493f4f3 100644 --- a/arch/arm/mach-exynos/include/mach/uncompress.h +++ b/arch/arm/mach-exynos/include/mach/uncompress.h @@ -1,9 +1,8 @@ -/* linux/arch/arm/mach-exynos4/include/mach/uncompress.h - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. +/* + * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * EXYNOS4 - uncompress code + * EXYNOS - uncompress code * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,12 +12,20 @@ #ifndef __ASM_ARCH_UNCOMPRESS_H #define __ASM_ARCH_UNCOMPRESS_H __FILE__ +#include + #include + +volatile u8 *uart_base; + #include static void arch_detect_cpu(void) { - /* we do not need to do any cpu detection here at the moment. */ + if (machine_is_smdk5250()) + uart_base = (volatile u8 *)EXYNOS5_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT); + else + uart_base = (volatile u8 *)EXYNOS4_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT); /* * For preventing FIFO overrun or infinite loop of UART console, diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 8167ce6..10e235cc7 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -40,6 +40,10 @@ config S5P_HRT help Use the High Resolution timer support +config S5P_DEV_UART + def_bool y + depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210) + config S5P_PM bool help diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 30d8c30..4bd8241 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -12,7 +12,6 @@ obj- := # Core files -obj-y += dev-uart.o obj-y += clock.o obj-y += irq.o obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o @@ -23,5 +22,7 @@ obj-$(CONFIG_S5P_SLEEP) += sleep.o obj-$(CONFIG_S5P_HRT) += s5p-time.o # devices + +obj-$(CONFIG_S5P_DEV_UART) += dev-uart.o obj-$(CONFIG_S5P_DEV_MFC) += dev-mfc.o obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 4214ea0..32cc67e 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -26,6 +26,8 @@ struct s3c24xx_uart_resources { extern struct s3c24xx_uart_resources s3c2410_uart_resources[]; extern struct s3c24xx_uart_resources s3c64xx_uart_resources[]; extern struct s3c24xx_uart_resources s5p_uart_resources[]; +extern struct s3c24xx_uart_resources exynos4_uart_resources[]; +extern struct s3c24xx_uart_resources exynos5_uart_resources[]; extern struct platform_device *s3c24xx_uart_devs[]; extern struct platform_device *s3c24xx_uart_src[]; diff --git a/arch/arm/plat-samsung/include/plat/uncompress.h b/arch/arm/plat-samsung/include/plat/uncompress.h index ee48e12..7e068d1 100644 --- a/arch/arm/plat-samsung/include/plat/uncompress.h +++ b/arch/arm/plat-samsung/include/plat/uncompress.h @@ -37,7 +37,9 @@ static void arch_detect_cpu(void); /* how many bytes we allow into the FIFO at a time in FIFO mode */ #define FIFO_MAX (14) +#ifdef S3C_PA_UART #define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT) +#endif static __inline__ void uart_wr(unsigned int reg, unsigned int val) -- cgit v0.10.2 From 94c7ca71c40ffcde28388a712cab524d636bec60 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sat, 11 Feb 2012 22:15:45 +0900 Subject: ARM: EXYNOS: add support for EXYNOS5250 SoC This patch add support for EXYNOS5250 SoC has two Cortex-A15 cores. Since actually, most codes in mach-exynos/ are used commonly for EXYNOS4 and EXYNOS5 the EXYNOS5/EXYNOS5250 has been implemented in mach-exynos/. Signed-off-by: Kukjin Kim diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 1683bfb..a826ffc 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -180,6 +180,7 @@ machine-$(CONFIG_ARCH_S5P64X0) := s5p64x0 machine-$(CONFIG_ARCH_S5PC100) := s5pc100 machine-$(CONFIG_ARCH_S5PV210) := s5pv210 machine-$(CONFIG_ARCH_EXYNOS4) := exynos +machine-$(CONFIG_ARCH_EXYNOS5) := exynos machine-$(CONFIG_ARCH_SA1100) := sa1100 machine-$(CONFIG_ARCH_SHARK) := shark machine-$(CONFIG_ARCH_SHMOBILE) := shmobile diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 4a82cf0..7fdb139 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -49,9 +49,12 @@ static const char name_exynos4210[] = "EXYNOS4210"; static const char name_exynos4212[] = "EXYNOS4212"; static const char name_exynos4412[] = "EXYNOS4412"; +static const char name_exynos5250[] = "EXYNOS5250"; static void exynos4_map_io(void); +static void exynos5_map_io(void); static void exynos4_init_clocks(int xtal); +static void exynos5_init_clocks(int xtal); static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no); static int exynos_init(void); @@ -80,6 +83,14 @@ static struct cpu_table cpu_ids[] __initdata = { .init_uarts = exynos_init_uarts, .init = exynos_init, .name = name_exynos4412, + }, { + .idcode = EXYNOS5250_SOC_ID, + .idmask = EXYNOS5_SOC_MASK, + .map_io = exynos5_map_io, + .init_clocks = exynos5_init_clocks, + .init_uarts = exynos_init_uarts, + .init = exynos_init, + .name = name_exynos5250, }, }; @@ -88,10 +99,14 @@ static struct cpu_table cpu_ids[] __initdata = { static struct map_desc exynos_iodesc[] __initdata = { { .virtual = (unsigned long)S5P_VA_CHIPID, - .pfn = __phys_to_pfn(EXYNOS4_PA_CHIPID), + .pfn = __phys_to_pfn(EXYNOS_PA_CHIPID), .length = SZ_4K, .type = MT_DEVICE, - }, { + }, +}; + +static struct map_desc exynos4_iodesc[] __initdata = { + { .virtual = (unsigned long)S3C_VA_SYS, .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON), .length = SZ_64K, @@ -141,11 +156,7 @@ static struct map_desc exynos_iodesc[] __initdata = { .pfn = __phys_to_pfn(EXYNOS4_PA_UART), .length = SZ_512K, .type = MT_DEVICE, - }, -}; - -static struct map_desc exynos4_iodesc[] __initdata = { - { + }, { .virtual = (unsigned long)S5P_VA_CMU, .pfn = __phys_to_pfn(EXYNOS4_PA_CMU), .length = SZ_128K, @@ -206,11 +217,80 @@ static struct map_desc exynos4_iodesc1[] __initdata = { }, }; +static struct map_desc exynos5_iodesc[] __initdata = { + { + .virtual = (unsigned long)S3C_VA_SYS, + .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON), + .length = SZ_64K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_TIMER, + .pfn = __phys_to_pfn(EXYNOS5_PA_TIMER), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_WATCHDOG, + .pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_SROMC, + .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_SYSTIMER, + .pfn = __phys_to_pfn(EXYNOS5_PA_SYSTIMER), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_SYSRAM, + .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_CMU, + .pfn = __phys_to_pfn(EXYNOS5_PA_CMU), + .length = 144 * SZ_1K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_PMU, + .pfn = __phys_to_pfn(EXYNOS5_PA_PMU), + .length = SZ_64K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_COMBINER_BASE, + .pfn = __phys_to_pfn(EXYNOS5_PA_COMBINER), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(EXYNOS5_PA_UART), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_GIC_CPU, + .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_CPU), + .length = SZ_64K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_GIC_DIST, + .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_DIST), + .length = SZ_64K, + .type = MT_DEVICE, + }, +}; + void exynos4_restart(char mode, const char *cmd) { __raw_writel(0x1, S5P_SWRESET); } +void exynos5_restart(char mode, const char *cmd) +{ + __raw_writel(0x1, EXYNOS_SWRESET); +} + /* * exynos_map_io * @@ -261,6 +341,16 @@ static void __init exynos4_map_io(void) s5p_hdmi_setname("exynos4-hdmi"); } +static void __init exynos5_map_io(void) +{ + iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc)); + + /* The I2C bus controllers are directly compatible with s3c2440 */ + s3c_i2c0_setname("s3c2440-i2c"); + s3c_i2c1_setname("s3c2440-i2c"); + s3c_i2c2_setname("s3c2440-i2c"); +} + static void __init exynos4_init_clocks(int xtal) { printk(KERN_DEBUG "%s: initializing clocks\n", __func__); @@ -277,6 +367,17 @@ static void __init exynos4_init_clocks(int xtal) exynos4_setup_clocks(); } +static void __init exynos5_init_clocks(int xtal) +{ + printk(KERN_DEBUG "%s: initializing clocks\n", __func__); + + s3c24xx_register_baseclocks(xtal); + s5p_register_clocks(xtal); + + exynos5_register_clocks(); + exynos5_setup_clocks(); +} + #define COMBINER_ENABLE_SET 0x0 #define COMBINER_ENABLE_CLEAR 0x4 #define COMBINER_INT_STATUS 0xC @@ -420,24 +521,59 @@ void __init exynos4_init_irq(void) s5p_init_irq(NULL, 0); } +void __init exynos5_init_irq(void) +{ + int irq; + + gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU); + + for (irq = 0; irq < MAX_COMBINER_NR; irq++) { + combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), + COMBINER_IRQ(irq, 0)); + combiner_cascade_irq(irq, IRQ_SPI(irq)); + } + + /* + * The parameters of s5p_init_irq() are for VIC init. + * Theses parameters should be NULL and 0 because EXYNOS4 + * uses GIC instead of VIC. + */ + s5p_init_irq(NULL, 0); +} + struct bus_type exynos4_subsys = { .name = "exynos4-core", .dev_name = "exynos4-core", }; +struct bus_type exynos5_subsys = { + .name = "exynos5-core", + .dev_name = "exynos5-core", +}; + static struct device exynos4_dev = { .bus = &exynos4_subsys, }; -static int __init exynos4_core_init(void) +static struct device exynos5_dev = { + .bus = &exynos5_subsys, +}; + +static int __init exynos_core_init(void) { - return subsys_system_register(&exynos4_subsys, NULL); + if (soc_is_exynos5250()) + return subsys_system_register(&exynos5_subsys, NULL); + else + return subsys_system_register(&exynos4_subsys, NULL); } -core_initcall(exynos4_core_init); +core_initcall(exynos_core_init); #ifdef CONFIG_CACHE_L2X0 static int __init exynos4_l2x0_cache_init(void) { + if (soc_is_exynos5250()) + return 0; + /* TAG, Data Latency Control: 2cycle */ __raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL); @@ -457,14 +593,42 @@ static int __init exynos4_l2x0_cache_init(void) return 0; } - early_initcall(exynos4_l2x0_cache_init); #endif +static int __init exynos5_l2_cache_init(void) +{ + unsigned int val; + + if (!soc_is_exynos5250()) + return 0; + + asm volatile("mrc p15, 0, %0, c1, c0, 0\n" + "bic %0, %0, #(1 << 2)\n" /* cache disable */ + "mcr p15, 0, %0, c1, c0, 0\n" + "mrc p15, 1, %0, c9, c0, 2\n" + : "=r"(val)); + + val |= (1 << 9) | (1 << 5) | (2 << 6) | (2 << 0); + + asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val)); + asm volatile("mrc p15, 0, %0, c1, c0, 0\n" + "orr %0, %0, #(1 << 2)\n" /* cache enable */ + "mcr p15, 0, %0, c1, c0, 0\n" + : : "r"(val)); + + return 0; +} +early_initcall(exynos5_l2_cache_init); + static int __init exynos_init(void) { printk(KERN_INFO "EXYNOS: Initializing architecture\n"); - return device_register(&exynos4_dev); + + if (soc_is_exynos5250()) + return device_register(&exynos5_dev); + else + return device_register(&exynos4_dev); } /* uart registration process */ @@ -673,6 +837,9 @@ static int __init exynos4_init_irq_eint(void) { int irq; + if (soc_is_exynos5250()) + return 0; + for (irq = 0 ; irq <= 31 ; irq++) { irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint, handle_level_irq); diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index b32c6b5..677b546 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -16,7 +16,9 @@ extern struct sys_timer exynos4_timer; void exynos_init_io(struct map_desc *mach_desc, int size); void exynos4_init_irq(void); +void exynos5_init_irq(void); void exynos4_restart(char mode, const char *cmd); +void exynos5_restart(char mode, const char *cmd); #ifdef CONFIG_ARCH_EXYNOS4 void exynos4_register_clocks(void); @@ -27,6 +29,15 @@ void exynos4_setup_clocks(void); #define exynos4_setup_clocks() #endif +#ifdef CONFIG_ARCH_EXYNOS5 +void exynos5_register_clocks(void); +void exynos5_setup_clocks(void); + +#else +#define exynos5_register_clocks() +#define exynos5_setup_clocks() +#endif + #ifdef CONFIG_CPU_EXYNOS4210 void exynos4210_register_clocks(void); diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index ea513c6..bf90bb0 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -25,6 +25,7 @@ #define EXYNOS4_PA_SYSRAM0 0x02025000 #define EXYNOS4_PA_SYSRAM1 0x02020000 +#define EXYNOS5_PA_SYSRAM 0x02020000 #define EXYNOS4_PA_FIMC0 0x11800000 #define EXYNOS4_PA_FIMC1 0x11810000 @@ -44,14 +45,23 @@ #define EXYNOS4_PA_ONENAND 0x0C000000 #define EXYNOS4_PA_ONENAND_DMA 0x0C600000 -#define EXYNOS4_PA_CHIPID 0x10000000 +#define EXYNOS_PA_CHIPID 0x10000000 #define EXYNOS4_PA_SYSCON 0x10010000 +#define EXYNOS5_PA_SYSCON 0x10050100 + #define EXYNOS4_PA_PMU 0x10020000 +#define EXYNOS5_PA_PMU 0x10040000 + #define EXYNOS4_PA_CMU 0x10030000 +#define EXYNOS5_PA_CMU 0x10010000 #define EXYNOS4_PA_SYSTIMER 0x10050000 +#define EXYNOS5_PA_SYSTIMER 0x101C0000 + #define EXYNOS4_PA_WATCHDOG 0x10060000 +#define EXYNOS5_PA_WATCHDOG 0x101D0000 + #define EXYNOS4_PA_RTC 0x10070000 #define EXYNOS4_PA_KEYPAD 0x100A0000 @@ -59,9 +69,12 @@ #define EXYNOS4_PA_DMC0 0x10400000 #define EXYNOS4_PA_COMBINER 0x10440000 +#define EXYNOS5_PA_COMBINER 0x10440000 #define EXYNOS4_PA_GIC_CPU 0x10480000 #define EXYNOS4_PA_GIC_DIST 0x10490000 +#define EXYNOS5_PA_GIC_CPU 0x10480000 +#define EXYNOS5_PA_GIC_DIST 0x10490000 #define EXYNOS4_PA_COREPERI 0x10500000 #define EXYNOS4_PA_TWD 0x10500600 @@ -92,7 +105,6 @@ #define EXYNOS4_PA_SPI1 0x13930000 #define EXYNOS4_PA_SPI2 0x13940000 - #define EXYNOS4_PA_GPIO1 0x11400000 #define EXYNOS4_PA_GPIO2 0x11000000 #define EXYNOS4_PA_GPIO3 0x03860000 @@ -110,6 +122,7 @@ #define EXYNOS4_PA_SATAPHY_CTRL 0x126B0000 #define EXYNOS4_PA_SROMC 0x12570000 +#define EXYNOS5_PA_SROMC 0x12250000 #define EXYNOS4_PA_EHCI 0x12580000 #define EXYNOS4_PA_OHCI 0x12590000 @@ -117,6 +130,7 @@ #define EXYNOS4_PA_MFC 0x13400000 #define EXYNOS4_PA_UART 0x13800000 +#define EXYNOS5_PA_UART 0x12C00000 #define EXYNOS4_PA_VP 0x12C00000 #define EXYNOS4_PA_MIXER 0x12C10000 @@ -125,6 +139,7 @@ #define EXYNOS4_PA_IIC_HDMIPHY 0x138E0000 #define EXYNOS4_PA_IIC(x) (0x13860000 + ((x) * 0x10000)) +#define EXYNOS5_PA_IIC(x) (0x12C60000 + ((x) * 0x10000)) #define EXYNOS4_PA_ADC 0x13910000 #define EXYNOS4_PA_ADC1 0x13911000 @@ -134,8 +149,10 @@ #define EXYNOS4_PA_SPDIF 0x139B0000 #define EXYNOS4_PA_TIMER 0x139D0000 +#define EXYNOS5_PA_TIMER 0x12DD0000 #define EXYNOS4_PA_SDRAM 0x40000000 +#define EXYNOS5_PA_SDRAM 0x40000000 /* Compatibiltiy Defines */ diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h index 4fff8e9..4c53f38 100644 --- a/arch/arm/mach-exynos/include/mach/regs-pmu.h +++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h @@ -31,6 +31,7 @@ #define S5P_USE_STANDBYWFE_ISP_ARM (1 << 26) #define S5P_SWRESET S5P_PMUREG(0x0400) +#define EXYNOS_SWRESET S5P_PMUREG(0x0400) #define S5P_WAKEUP_STAT S5P_PMUREG(0x0600) #define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604) diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 10e235cc7..88795ea 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -9,8 +9,8 @@ config PLAT_S5P bool depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) default y - select ARM_VIC if !ARCH_EXYNOS4 - select ARM_GIC if ARCH_EXYNOS4 + select ARM_VIC if !ARCH_EXYNOS + select ARM_GIC if ARCH_EXYNOS select GIC_NON_BANKED if ARCH_EXYNOS4 select NO_IOPORT select ARCH_REQUIRE_GPIOLIB diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index 73cb3cf..787ceac 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -42,6 +42,9 @@ extern unsigned long samsung_cpu_id; #define EXYNOS4412_CPU_ID 0xE4412200 #define EXYNOS4_CPU_MASK 0xFFFE0000 +#define EXYNOS5250_SOC_ID 0x43520000 +#define EXYNOS5_SOC_MASK 0xFFFFF000 + #define IS_SAMSUNG_CPU(name, id, mask) \ static inline int is_samsung_##name(void) \ { \ @@ -58,6 +61,7 @@ IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK) IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK) IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK) IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK) +IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK) #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \ defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \ @@ -120,6 +124,12 @@ IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK) #define EXYNOS4210_REV_1_0 (0x10) #define EXYNOS4210_REV_1_1 (0x11) +#if defined(CONFIG_SOC_EXYNOS5250) +# define soc_is_exynos5250() is_samsung_exynos5250() +#else +# define soc_is_exynos5250() 0 +#endif + #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } #ifndef MHZ -- cgit v0.10.2 From bb19a7513dffc82f4b474ed90fc8ed691b54768b Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Wed, 25 Jan 2012 13:48:11 +0900 Subject: ARM: EXYNOS: add interrupt definitions for EXYNOS5250 This patch adds the interrupt definitions for EXYNOS5250 at file and it is needed for EXYNOS5250 SoC. As a note, for single zImage of EXYNOS4 and EXYNOS5, prefix of EXYNOS4_ and EXYNOS5_ has been added. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 7fdb139..4ef0cb5 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -345,6 +345,11 @@ static void __init exynos5_map_io(void) { iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc)); + s3c_device_i2c0.resource[0].start = EXYNOS5_PA_IIC(0); + s3c_device_i2c0.resource[0].end = EXYNOS5_PA_IIC(0) + SZ_4K - 1; + s3c_device_i2c0.resource[1].start = EXYNOS5_IRQ_IIC; + s3c_device_i2c0.resource[1].end = EXYNOS5_IRQ_IIC; + /* The I2C bus controllers are directly compatible with s3c2440 */ s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); @@ -451,7 +456,14 @@ static struct irq_chip combiner_chip = { static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq) { - if (combiner_nr >= MAX_COMBINER_NR) + unsigned int max_nr; + + if (soc_is_exynos5250()) + max_nr = EXYNOS5_MAX_COMBINER_NR; + else + max_nr = EXYNOS4_MAX_COMBINER_NR; + + if (combiner_nr >= max_nr) BUG(); if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0) BUG(); @@ -462,8 +474,14 @@ static void __init combiner_init(unsigned int combiner_nr, void __iomem *base, unsigned int irq_start) { unsigned int i; + unsigned int max_nr; - if (combiner_nr >= MAX_COMBINER_NR) + if (soc_is_exynos5250()) + max_nr = EXYNOS5_MAX_COMBINER_NR; + else + max_nr = EXYNOS4_MAX_COMBINER_NR; + + if (combiner_nr >= max_nr) BUG(); combiner_data[combiner_nr].base = base; @@ -506,7 +524,7 @@ void __init exynos4_init_irq(void) of_irq_init(exynos4_dt_irq_match); #endif - for (irq = 0; irq < MAX_COMBINER_NR; irq++) { + for (irq = 0; irq < EXYNOS4_MAX_COMBINER_NR; irq++) { combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), COMBINER_IRQ(irq, 0)); @@ -527,7 +545,7 @@ void __init exynos5_init_irq(void) gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU); - for (irq = 0; irq < MAX_COMBINER_NR; irq++) { + for (irq = 0; irq < EXYNOS5_MAX_COMBINER_NR; irq++) { combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), COMBINER_IRQ(irq, 0)); combiner_cascade_irq(irq, IRQ_SPI(irq)); @@ -651,27 +669,43 @@ static DEFINE_SPINLOCK(eint_lock); static unsigned int eint0_15_data[16]; -static unsigned int exynos4_get_irq_nr(unsigned int number) -{ - u32 ret = 0; - - switch (number) { - case 0 ... 3: - ret = (number + IRQ_EINT0); - break; - case 4 ... 7: - ret = (number + (IRQ_EINT4 - 4)); - break; - case 8 ... 15: - ret = (number + (IRQ_EINT8 - 8)); - break; - default: - printk(KERN_ERR "number available : %d\n", number); - } - - return ret; -} +static unsigned int exynos4_eint0_15_src_int[16] = { + EXYNOS4_IRQ_EINT0, + EXYNOS4_IRQ_EINT1, + EXYNOS4_IRQ_EINT2, + EXYNOS4_IRQ_EINT3, + EXYNOS4_IRQ_EINT4, + EXYNOS4_IRQ_EINT5, + EXYNOS4_IRQ_EINT6, + EXYNOS4_IRQ_EINT7, + EXYNOS4_IRQ_EINT8, + EXYNOS4_IRQ_EINT9, + EXYNOS4_IRQ_EINT10, + EXYNOS4_IRQ_EINT11, + EXYNOS4_IRQ_EINT12, + EXYNOS4_IRQ_EINT13, + EXYNOS4_IRQ_EINT14, + EXYNOS4_IRQ_EINT15, +}; +static unsigned int exynos5_eint0_15_src_int[16] = { + EXYNOS5_IRQ_EINT0, + EXYNOS5_IRQ_EINT1, + EXYNOS5_IRQ_EINT2, + EXYNOS5_IRQ_EINT3, + EXYNOS5_IRQ_EINT4, + EXYNOS5_IRQ_EINT5, + EXYNOS5_IRQ_EINT6, + EXYNOS5_IRQ_EINT7, + EXYNOS5_IRQ_EINT8, + EXYNOS5_IRQ_EINT9, + EXYNOS5_IRQ_EINT10, + EXYNOS5_IRQ_EINT11, + EXYNOS5_IRQ_EINT12, + EXYNOS5_IRQ_EINT13, + EXYNOS5_IRQ_EINT14, + EXYNOS5_IRQ_EINT15, +}; static inline void exynos4_irq_eint_mask(struct irq_data *data) { u32 mask; @@ -816,7 +850,7 @@ static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) chained_irq_exit(chip, desc); } -static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc) +static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) { u32 *irq_data = irq_get_handler_data(irq); struct irq_chip *chip = irq_get_chip(irq); @@ -846,15 +880,22 @@ static int __init exynos4_init_irq_eint(void) set_irq_flags(IRQ_EINT(irq), IRQF_VALID); } - irq_set_chained_handler(IRQ_EINT16_31, exynos4_irq_demux_eint16_31); + irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos4_irq_demux_eint16_31); for (irq = 0 ; irq <= 15 ; irq++) { eint0_15_data[irq] = IRQ_EINT(irq); - irq_set_handler_data(exynos4_get_irq_nr(irq), - &eint0_15_data[irq]); - irq_set_chained_handler(exynos4_get_irq_nr(irq), - exynos4_irq_eint0_15); + if (soc_is_exynos5250()) { + irq_set_handler_data(exynos5_eint0_15_src_int[irq], + &eint0_15_data[irq]); + irq_set_chained_handler(exynos5_eint0_15_src_int[irq], + exynos_irq_eint0_15); + } else { + irq_set_handler_data(exynos4_eint0_15_src_int[irq], + &eint0_15_data[irq]); + irq_set_chained_handler(exynos4_eint0_15_src_int[irq], + exynos_irq_eint0_15); + } } return 0; diff --git a/arch/arm/mach-exynos/dev-ahci.c b/arch/arm/mach-exynos/dev-ahci.c index f57a3de..50ce5b0 100644 --- a/arch/arm/mach-exynos/dev-ahci.c +++ b/arch/arm/mach-exynos/dev-ahci.c @@ -242,8 +242,8 @@ static struct resource exynos4_ahci_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_SATA, - .end = IRQ_SATA, + .start = EXYNOS4_IRQ_SATA, + .end = EXYNOS4_IRQ_SATA, .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/arm/mach-exynos/dev-audio.c b/arch/arm/mach-exynos/dev-audio.c index 5a9f9c2e..7199e1a 100644 --- a/arch/arm/mach-exynos/dev-audio.c +++ b/arch/arm/mach-exynos/dev-audio.c @@ -304,8 +304,8 @@ static struct resource exynos4_ac97_resource[] = { .flags = IORESOURCE_DMA, }, [4] = { - .start = IRQ_AC97, - .end = IRQ_AC97, + .start = EXYNOS4_IRQ_AC97, + .end = EXYNOS4_IRQ_AC97, .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c index 13607c4..3983abe 100644 --- a/arch/arm/mach-exynos/dma.c +++ b/arch/arm/mach-exynos/dma.c @@ -108,7 +108,7 @@ static u8 exynos4212_pdma0_peri[] = { struct dma_pl330_platdata exynos4_pdma0_pdata; static AMBA_AHB_DEVICE(exynos4_pdma0, "dma-pl330.0", 0x00041330, - EXYNOS4_PA_PDMA0, {IRQ_PDMA0}, &exynos4_pdma0_pdata); + EXYNOS4_PA_PDMA0, {EXYNOS4_IRQ_PDMA0}, &exynos4_pdma0_pdata); static u8 exynos4210_pdma1_peri[] = { DMACH_PCM0_RX, @@ -174,7 +174,7 @@ static u8 exynos4212_pdma1_peri[] = { static struct dma_pl330_platdata exynos4_pdma1_pdata; static AMBA_AHB_DEVICE(exynos4_pdma1, "dma-pl330.1", 0x00041330, - EXYNOS4_PA_PDMA1, {IRQ_PDMA1}, &exynos4_pdma1_pdata); + EXYNOS4_PA_PDMA1, {EXYNOS4_IRQ_PDMA1}, &exynos4_pdma1_pdata); static u8 mdma_peri[] = { DMACH_MTOM_0, @@ -193,7 +193,7 @@ static struct dma_pl330_platdata exynos4_mdma1_pdata = { }; static AMBA_AHB_DEVICE(exynos4_mdma1, "dma-pl330.2", 0x00041330, - EXYNOS4_PA_MDMA1, {IRQ_MDMA1}, &exynos4_mdma1_pdata); + EXYNOS4_PA_MDMA1, {EXYNOS4_IRQ_MDMA1}, &exynos4_mdma1_pdata); static int __init exynos4_dma_init(void) { diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index f78070e..9bee853 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h @@ -1,9 +1,8 @@ -/* linux/arch/arm/mach-exynos4/include/mach/irqs.h - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. +/* + * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * EXYNOS4 - IRQ definitions + * EXYNOS - IRQ 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 @@ -17,172 +16,450 @@ /* PPI: Private Peripheral Interrupt */ -#define IRQ_PPI(x) (x+16) - -#define IRQ_MCT_LOCALTIMER IRQ_PPI(12) +#define IRQ_PPI(x) (x + 16) /* SPI: Shared Peripheral Interrupt */ -#define IRQ_SPI(x) (x+32) - -#define IRQ_EINT0 IRQ_SPI(16) -#define IRQ_EINT1 IRQ_SPI(17) -#define IRQ_EINT2 IRQ_SPI(18) -#define IRQ_EINT3 IRQ_SPI(19) -#define IRQ_EINT4 IRQ_SPI(20) -#define IRQ_EINT5 IRQ_SPI(21) -#define IRQ_EINT6 IRQ_SPI(22) -#define IRQ_EINT7 IRQ_SPI(23) -#define IRQ_EINT8 IRQ_SPI(24) -#define IRQ_EINT9 IRQ_SPI(25) -#define IRQ_EINT10 IRQ_SPI(26) -#define IRQ_EINT11 IRQ_SPI(27) -#define IRQ_EINT12 IRQ_SPI(28) -#define IRQ_EINT13 IRQ_SPI(29) -#define IRQ_EINT14 IRQ_SPI(30) -#define IRQ_EINT15 IRQ_SPI(31) -#define IRQ_EINT16_31 IRQ_SPI(32) - -#define IRQ_MDMA0 IRQ_SPI(33) -#define IRQ_MDMA1 IRQ_SPI(34) -#define IRQ_PDMA0 IRQ_SPI(35) -#define IRQ_PDMA1 IRQ_SPI(36) -#define IRQ_TIMER0_VIC IRQ_SPI(37) -#define IRQ_TIMER1_VIC IRQ_SPI(38) -#define IRQ_TIMER2_VIC IRQ_SPI(39) -#define IRQ_TIMER3_VIC IRQ_SPI(40) -#define IRQ_TIMER4_VIC IRQ_SPI(41) -#define IRQ_MCT_L0 IRQ_SPI(42) -#define IRQ_WDT IRQ_SPI(43) -#define IRQ_RTC_ALARM IRQ_SPI(44) -#define IRQ_RTC_TIC IRQ_SPI(45) -#define IRQ_GPIO_XB IRQ_SPI(46) -#define IRQ_GPIO_XA IRQ_SPI(47) -#define IRQ_MCT_L1 IRQ_SPI(48) - -#define IRQ_UART0 IRQ_SPI(52) -#define IRQ_UART1 IRQ_SPI(53) -#define IRQ_UART2 IRQ_SPI(54) -#define IRQ_UART3 IRQ_SPI(55) -#define IRQ_UART4 IRQ_SPI(56) -#define IRQ_MCT_G0 IRQ_SPI(57) -#define IRQ_IIC IRQ_SPI(58) -#define IRQ_IIC1 IRQ_SPI(59) -#define IRQ_IIC2 IRQ_SPI(60) -#define IRQ_IIC3 IRQ_SPI(61) -#define IRQ_IIC4 IRQ_SPI(62) -#define IRQ_IIC5 IRQ_SPI(63) -#define IRQ_IIC6 IRQ_SPI(64) -#define IRQ_IIC7 IRQ_SPI(65) -#define IRQ_SPI0 IRQ_SPI(66) -#define IRQ_SPI1 IRQ_SPI(67) -#define IRQ_SPI2 IRQ_SPI(68) - -#define IRQ_USB_HOST IRQ_SPI(70) -#define IRQ_USB_HSOTG IRQ_SPI(71) -#define IRQ_MODEM_IF IRQ_SPI(72) -#define IRQ_HSMMC0 IRQ_SPI(73) -#define IRQ_HSMMC1 IRQ_SPI(74) -#define IRQ_HSMMC2 IRQ_SPI(75) -#define IRQ_HSMMC3 IRQ_SPI(76) -#define IRQ_DWMCI IRQ_SPI(77) - -#define IRQ_MIPI_CSIS0 IRQ_SPI(78) -#define IRQ_MIPI_CSIS1 IRQ_SPI(80) - -#define IRQ_ONENAND_AUDI IRQ_SPI(82) -#define IRQ_ROTATOR IRQ_SPI(83) -#define IRQ_FIMC0 IRQ_SPI(84) -#define IRQ_FIMC1 IRQ_SPI(85) -#define IRQ_FIMC2 IRQ_SPI(86) -#define IRQ_FIMC3 IRQ_SPI(87) -#define IRQ_JPEG IRQ_SPI(88) -#define IRQ_2D IRQ_SPI(89) -#define IRQ_PCIE IRQ_SPI(90) - -#define IRQ_MIXER IRQ_SPI(91) -#define IRQ_HDMI IRQ_SPI(92) -#define IRQ_IIC_HDMIPHY IRQ_SPI(93) -#define IRQ_MFC IRQ_SPI(94) -#define IRQ_SDO IRQ_SPI(95) - -#define IRQ_AUDIO_SS IRQ_SPI(96) -#define IRQ_I2S0 IRQ_SPI(97) -#define IRQ_I2S1 IRQ_SPI(98) -#define IRQ_I2S2 IRQ_SPI(99) -#define IRQ_AC97 IRQ_SPI(100) - -#define IRQ_SPDIF IRQ_SPI(104) -#define IRQ_ADC0 IRQ_SPI(105) -#define IRQ_PEN0 IRQ_SPI(106) -#define IRQ_ADC1 IRQ_SPI(107) -#define IRQ_PEN1 IRQ_SPI(108) -#define IRQ_KEYPAD IRQ_SPI(109) -#define IRQ_PMU IRQ_SPI(110) -#define IRQ_GPS IRQ_SPI(111) -#define IRQ_INTFEEDCTRL_SSS IRQ_SPI(112) -#define IRQ_SLIMBUS IRQ_SPI(113) - -#define IRQ_TSI IRQ_SPI(115) -#define IRQ_SATA IRQ_SPI(116) - -#define MAX_IRQ_IN_COMBINER 8 -#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128)) -#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y) - -#define IRQ_SYSMMU_MDMA0_0 COMBINER_IRQ(4, 0) -#define IRQ_SYSMMU_SSS_0 COMBINER_IRQ(4, 1) -#define IRQ_SYSMMU_FIMC0_0 COMBINER_IRQ(4, 2) -#define IRQ_SYSMMU_FIMC1_0 COMBINER_IRQ(4, 3) -#define IRQ_SYSMMU_FIMC2_0 COMBINER_IRQ(4, 4) -#define IRQ_SYSMMU_FIMC3_0 COMBINER_IRQ(4, 5) -#define IRQ_SYSMMU_JPEG_0 COMBINER_IRQ(4, 6) -#define IRQ_SYSMMU_2D_0 COMBINER_IRQ(4, 7) - -#define IRQ_SYSMMU_ROTATOR_0 COMBINER_IRQ(5, 0) -#define IRQ_SYSMMU_MDMA1_0 COMBINER_IRQ(5, 1) -#define IRQ_SYSMMU_LCD0_M0_0 COMBINER_IRQ(5, 2) -#define IRQ_SYSMMU_LCD1_M1_0 COMBINER_IRQ(5, 3) -#define IRQ_SYSMMU_TV_M0_0 COMBINER_IRQ(5, 4) -#define IRQ_SYSMMU_MFC_M0_0 COMBINER_IRQ(5, 5) -#define IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6) -#define IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7) - -#define IRQ_FIMD0_FIFO COMBINER_IRQ(11, 0) -#define IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1) -#define IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2) - -#define MAX_COMBINER_NR 16 - -#define IRQ_ADC IRQ_ADC0 -#define IRQ_TC IRQ_PEN0 - -#define S5P_IRQ_EINT_BASE COMBINER_IRQ(MAX_COMBINER_NR, 0) - -#define S5P_EINT_BASE1 (S5P_IRQ_EINT_BASE + 0) -#define S5P_EINT_BASE2 (S5P_IRQ_EINT_BASE + 16) - -/* optional GPIO interrupts */ -#define S5P_GPIOINT_BASE (S5P_IRQ_EINT_BASE + 32) -#define IRQ_GPIO1_NR_GROUPS 16 -#define IRQ_GPIO2_NR_GROUPS 9 -#define IRQ_GPIO_END (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT) - -#define IRQ_TIMER_BASE (IRQ_GPIO_END + 64) +#define IRQ_SPI(x) (x + 32) -/* Set the default NR_IRQS */ -#define NR_IRQS (IRQ_TIMER_BASE + IRQ_TIMER_COUNT) +/* COMBINER */ + +#define MAX_IRQ_IN_COMBINER 8 +#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128)) +#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y) + +/* For EXYNOS4 and EXYNOS5 */ + +#define EXYNOS_IRQ_MCT_LOCALTIMER IRQ_PPI(12) + +#define EXYNOS_IRQ_EINT16_31 IRQ_SPI(32) + +/* For EXYNOS4 SoCs */ + +#define EXYNOS4_IRQ_EINT0 IRQ_SPI(16) +#define EXYNOS4_IRQ_EINT1 IRQ_SPI(17) +#define EXYNOS4_IRQ_EINT2 IRQ_SPI(18) +#define EXYNOS4_IRQ_EINT3 IRQ_SPI(19) +#define EXYNOS4_IRQ_EINT4 IRQ_SPI(20) +#define EXYNOS4_IRQ_EINT5 IRQ_SPI(21) +#define EXYNOS4_IRQ_EINT6 IRQ_SPI(22) +#define EXYNOS4_IRQ_EINT7 IRQ_SPI(23) +#define EXYNOS4_IRQ_EINT8 IRQ_SPI(24) +#define EXYNOS4_IRQ_EINT9 IRQ_SPI(25) +#define EXYNOS4_IRQ_EINT10 IRQ_SPI(26) +#define EXYNOS4_IRQ_EINT11 IRQ_SPI(27) +#define EXYNOS4_IRQ_EINT12 IRQ_SPI(28) +#define EXYNOS4_IRQ_EINT13 IRQ_SPI(29) +#define EXYNOS4_IRQ_EINT14 IRQ_SPI(30) +#define EXYNOS4_IRQ_EINT15 IRQ_SPI(31) + +#define EXYNOS4_IRQ_MDMA0 IRQ_SPI(33) +#define EXYNOS4_IRQ_MDMA1 IRQ_SPI(34) +#define EXYNOS4_IRQ_PDMA0 IRQ_SPI(35) +#define EXYNOS4_IRQ_PDMA1 IRQ_SPI(36) +#define EXYNOS4_IRQ_TIMER0_VIC IRQ_SPI(37) +#define EXYNOS4_IRQ_TIMER1_VIC IRQ_SPI(38) +#define EXYNOS4_IRQ_TIMER2_VIC IRQ_SPI(39) +#define EXYNOS4_IRQ_TIMER3_VIC IRQ_SPI(40) +#define EXYNOS4_IRQ_TIMER4_VIC IRQ_SPI(41) +#define EXYNOS4_IRQ_MCT_L0 IRQ_SPI(42) +#define EXYNOS4_IRQ_WDT IRQ_SPI(43) +#define EXYNOS4_IRQ_RTC_ALARM IRQ_SPI(44) +#define EXYNOS4_IRQ_RTC_TIC IRQ_SPI(45) +#define EXYNOS4_IRQ_GPIO_XB IRQ_SPI(46) +#define EXYNOS4_IRQ_GPIO_XA IRQ_SPI(47) +#define EXYNOS4_IRQ_MCT_L1 IRQ_SPI(48) #define EXYNOS4_IRQ_UART0 IRQ_SPI(52) #define EXYNOS4_IRQ_UART1 IRQ_SPI(53) #define EXYNOS4_IRQ_UART2 IRQ_SPI(54) #define EXYNOS4_IRQ_UART3 IRQ_SPI(55) #define EXYNOS4_IRQ_UART4 IRQ_SPI(56) +#define EXYNOS4_IRQ_MCT_G0 IRQ_SPI(57) +#define EXYNOS4_IRQ_IIC IRQ_SPI(58) +#define EXYNOS4_IRQ_IIC1 IRQ_SPI(59) +#define EXYNOS4_IRQ_IIC2 IRQ_SPI(60) +#define EXYNOS4_IRQ_IIC3 IRQ_SPI(61) +#define EXYNOS4_IRQ_IIC4 IRQ_SPI(62) +#define EXYNOS4_IRQ_IIC5 IRQ_SPI(63) +#define EXYNOS4_IRQ_IIC6 IRQ_SPI(64) +#define EXYNOS4_IRQ_IIC7 IRQ_SPI(65) +#define EXYNOS4_IRQ_SPI0 IRQ_SPI(66) +#define EXYNOS4_IRQ_SPI1 IRQ_SPI(67) +#define EXYNOS4_IRQ_SPI2 IRQ_SPI(68) + +#define EXYNOS4_IRQ_USB_HOST IRQ_SPI(70) +#define EXYNOS4_IRQ_USB_HSOTG IRQ_SPI(71) +#define EXYNOS4_IRQ_MODEM_IF IRQ_SPI(72) +#define EXYNOS4_IRQ_HSMMC0 IRQ_SPI(73) +#define EXYNOS4_IRQ_HSMMC1 IRQ_SPI(74) +#define EXYNOS4_IRQ_HSMMC2 IRQ_SPI(75) +#define EXYNOS4_IRQ_HSMMC3 IRQ_SPI(76) +#define EXYNOS4_IRQ_DWMCI IRQ_SPI(77) + +#define EXYNOS4_IRQ_MIPI_CSIS0 IRQ_SPI(78) +#define EXYNOS4_IRQ_MIPI_CSIS1 IRQ_SPI(80) + +#define EXYNOS4_IRQ_ONENAND_AUDI IRQ_SPI(82) +#define EXYNOS4_IRQ_ROTATOR IRQ_SPI(83) +#define EXYNOS4_IRQ_FIMC0 IRQ_SPI(84) +#define EXYNOS4_IRQ_FIMC1 IRQ_SPI(85) +#define EXYNOS4_IRQ_FIMC2 IRQ_SPI(86) +#define EXYNOS4_IRQ_FIMC3 IRQ_SPI(87) +#define EXYNOS4_IRQ_JPEG IRQ_SPI(88) +#define EXYNOS4_IRQ_2D IRQ_SPI(89) +#define EXYNOS4_IRQ_PCIE IRQ_SPI(90) + +#define EXYNOS4_IRQ_MIXER IRQ_SPI(91) +#define EXYNOS4_IRQ_HDMI IRQ_SPI(92) +#define EXYNOS4_IRQ_IIC_HDMIPHY IRQ_SPI(93) +#define EXYNOS4_IRQ_MFC IRQ_SPI(94) +#define EXYNOS4_IRQ_SDO IRQ_SPI(95) + +#define EXYNOS4_IRQ_AUDIO_SS IRQ_SPI(96) +#define EXYNOS4_IRQ_I2S0 IRQ_SPI(97) +#define EXYNOS4_IRQ_I2S1 IRQ_SPI(98) +#define EXYNOS4_IRQ_I2S2 IRQ_SPI(99) +#define EXYNOS4_IRQ_AC97 IRQ_SPI(100) + +#define EXYNOS4_IRQ_SPDIF IRQ_SPI(104) +#define EXYNOS4_IRQ_ADC0 IRQ_SPI(105) +#define EXYNOS4_IRQ_PEN0 IRQ_SPI(106) +#define EXYNOS4_IRQ_ADC1 IRQ_SPI(107) +#define EXYNOS4_IRQ_PEN1 IRQ_SPI(108) +#define EXYNOS4_IRQ_KEYPAD IRQ_SPI(109) +#define EXYNOS4_IRQ_PMU IRQ_SPI(110) +#define EXYNOS4_IRQ_GPS IRQ_SPI(111) +#define EXYNOS4_IRQ_INTFEEDCTRL_SSS IRQ_SPI(112) +#define EXYNOS4_IRQ_SLIMBUS IRQ_SPI(113) + +#define EXYNOS4_IRQ_TSI IRQ_SPI(115) +#define EXYNOS4_IRQ_SATA IRQ_SPI(116) + +#define EXYNOS4_IRQ_SYSMMU_MDMA0_0 COMBINER_IRQ(4, 0) +#define EXYNOS4_IRQ_SYSMMU_SSS_0 COMBINER_IRQ(4, 1) +#define EXYNOS4_IRQ_SYSMMU_FIMC0_0 COMBINER_IRQ(4, 2) +#define EXYNOS4_IRQ_SYSMMU_FIMC1_0 COMBINER_IRQ(4, 3) +#define EXYNOS4_IRQ_SYSMMU_FIMC2_0 COMBINER_IRQ(4, 4) +#define EXYNOS4_IRQ_SYSMMU_FIMC3_0 COMBINER_IRQ(4, 5) +#define EXYNOS4_IRQ_SYSMMU_JPEG_0 COMBINER_IRQ(4, 6) +#define EXYNOS4_IRQ_SYSMMU_2D_0 COMBINER_IRQ(4, 7) + +#define EXYNOS4_IRQ_SYSMMU_ROTATOR_0 COMBINER_IRQ(5, 0) +#define EXYNOS4_IRQ_SYSMMU_MDMA1_0 COMBINER_IRQ(5, 1) +#define EXYNOS4_IRQ_SYSMMU_LCD0_M0_0 COMBINER_IRQ(5, 2) +#define EXYNOS4_IRQ_SYSMMU_LCD1_M1_0 COMBINER_IRQ(5, 3) +#define EXYNOS4_IRQ_SYSMMU_TV_M0_0 COMBINER_IRQ(5, 4) +#define EXYNOS4_IRQ_SYSMMU_MFC_M0_0 COMBINER_IRQ(5, 5) +#define EXYNOS4_IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6) +#define EXYNOS4_IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7) + +#define EXYNOS4_IRQ_FIMD0_FIFO COMBINER_IRQ(11, 0) +#define EXYNOS4_IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1) +#define EXYNOS4_IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2) + +#define EXYNOS4_MAX_COMBINER_NR 16 + +#define EXYNOS4_IRQ_GPIO1_NR_GROUPS 16 +#define EXYNOS4_IRQ_GPIO2_NR_GROUPS 9 + +/* + * For Compatibility: + * the default is for EXYNOS4, and + * for exynos5, should be re-mapped at function + */ + +#define IRQ_TIMER0_VIC EXYNOS4_IRQ_TIMER0_VIC +#define IRQ_TIMER1_VIC EXYNOS4_IRQ_TIMER1_VIC +#define IRQ_TIMER2_VIC EXYNOS4_IRQ_TIMER2_VIC +#define IRQ_TIMER3_VIC EXYNOS4_IRQ_TIMER3_VIC +#define IRQ_TIMER4_VIC EXYNOS4_IRQ_TIMER4_VIC + +#define IRQ_WDT EXYNOS4_IRQ_WDT +#define IRQ_RTC_ALARM EXYNOS4_IRQ_RTC_ALARM +#define IRQ_RTC_TIC EXYNOS4_IRQ_RTC_TIC +#define IRQ_GPIO_XB EXYNOS4_IRQ_GPIO_XB +#define IRQ_GPIO_XA EXYNOS4_IRQ_GPIO_XA + +#define IRQ_IIC EXYNOS4_IRQ_IIC +#define IRQ_IIC1 EXYNOS4_IRQ_IIC1 +#define IRQ_IIC3 EXYNOS4_IRQ_IIC3 +#define IRQ_IIC5 EXYNOS4_IRQ_IIC5 +#define IRQ_IIC6 EXYNOS4_IRQ_IIC6 +#define IRQ_IIC7 EXYNOS4_IRQ_IIC7 + +#define IRQ_USB_HOST EXYNOS4_IRQ_USB_HOST + +#define IRQ_HSMMC0 EXYNOS4_IRQ_HSMMC0 +#define IRQ_HSMMC1 EXYNOS4_IRQ_HSMMC1 +#define IRQ_HSMMC2 EXYNOS4_IRQ_HSMMC2 +#define IRQ_HSMMC3 EXYNOS4_IRQ_HSMMC3 + +#define IRQ_MIPI_CSIS0 EXYNOS4_IRQ_MIPI_CSIS0 + +#define IRQ_ONENAND_AUDI EXYNOS4_IRQ_ONENAND_AUDI + +#define IRQ_FIMC0 EXYNOS4_IRQ_FIMC0 +#define IRQ_FIMC1 EXYNOS4_IRQ_FIMC1 +#define IRQ_FIMC2 EXYNOS4_IRQ_FIMC2 +#define IRQ_FIMC3 EXYNOS4_IRQ_FIMC3 +#define IRQ_JPEG EXYNOS4_IRQ_JPEG +#define IRQ_2D EXYNOS4_IRQ_2D + +#define IRQ_MIXER EXYNOS4_IRQ_MIXER +#define IRQ_HDMI EXYNOS4_IRQ_HDMI +#define IRQ_IIC_HDMIPHY EXYNOS4_IRQ_IIC_HDMIPHY +#define IRQ_MFC EXYNOS4_IRQ_MFC +#define IRQ_SDO EXYNOS4_IRQ_SDO + +#define IRQ_ADC EXYNOS4_IRQ_ADC0 +#define IRQ_TC EXYNOS4_IRQ_PEN0 + +#define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD +#define IRQ_PMU EXYNOS4_IRQ_PMU + +#define IRQ_SYSMMU_MDMA0_0 EXYNOS4_IRQ_SYSMMU_MDMA0_0 +#define IRQ_SYSMMU_SSS_0 EXYNOS4_IRQ_SYSMMU_SSS_0 +#define IRQ_SYSMMU_FIMC0_0 EXYNOS4_IRQ_SYSMMU_FIMC0_0 +#define IRQ_SYSMMU_FIMC1_0 EXYNOS4_IRQ_SYSMMU_FIMC1_0 +#define IRQ_SYSMMU_FIMC2_0 EXYNOS4_IRQ_SYSMMU_FIMC2_0 +#define IRQ_SYSMMU_FIMC3_0 EXYNOS4_IRQ_SYSMMU_FIMC3_0 +#define IRQ_SYSMMU_JPEG_0 EXYNOS4_IRQ_SYSMMU_JPEG_0 +#define IRQ_SYSMMU_2D_0 EXYNOS4_IRQ_SYSMMU_2D_0 +#define IRQ_SYSMMU_ROTATOR_0 EXYNOS4_IRQ_SYSMMU_ROTATOR_0 +#define IRQ_SYSMMU_MDMA1_0 EXYNOS4_IRQ_SYSMMU_MDMA1_0 +#define IRQ_SYSMMU_LCD0_M0_0 EXYNOS4_IRQ_SYSMMU_LCD0_M0_0 +#define IRQ_SYSMMU_LCD1_M1_0 EXYNOS4_IRQ_SYSMMU_LCD1_M1_0 +#define IRQ_SYSMMU_TV_M0_0 EXYNOS4_IRQ_SYSMMU_TV_M0_0 +#define IRQ_SYSMMU_MFC_M0_0 EXYNOS4_IRQ_SYSMMU_MFC_M0_0 +#define IRQ_SYSMMU_MFC_M1_0 EXYNOS4_IRQ_SYSMMU_MFC_M1_0 +#define IRQ_SYSMMU_PCIE_0 EXYNOS4_IRQ_SYSMMU_PCIE_0 + +#define IRQ_FIMD0_FIFO EXYNOS4_IRQ_FIMD0_FIFO +#define IRQ_FIMD0_VSYNC EXYNOS4_IRQ_FIMD0_VSYNC +#define IRQ_FIMD0_SYSTEM EXYNOS4_IRQ_FIMD0_SYSTEM + +#define IRQ_GPIO1_NR_GROUPS EXYNOS4_IRQ_GPIO1_NR_GROUPS +#define IRQ_GPIO2_NR_GROUPS EXYNOS4_IRQ_GPIO2_NR_GROUPS + +/* For EXYNOS5 SoCs */ + +#define EXYNOS5_IRQ_MDMA0 IRQ_SPI(33) +#define EXYNOS5_IRQ_PDMA0 IRQ_SPI(34) +#define EXYNOS5_IRQ_PDMA1 IRQ_SPI(35) +#define EXYNOS5_IRQ_TIMER0_VIC IRQ_SPI(36) +#define EXYNOS5_IRQ_TIMER1_VIC IRQ_SPI(37) +#define EXYNOS5_IRQ_TIMER2_VIC IRQ_SPI(38) +#define EXYNOS5_IRQ_TIMER3_VIC IRQ_SPI(39) +#define EXYNOS5_IRQ_TIMER4_VIC IRQ_SPI(40) +#define EXYNOS5_IRQ_RTIC IRQ_SPI(41) +#define EXYNOS5_IRQ_WDT IRQ_SPI(42) +#define EXYNOS5_IRQ_RTC_ALARM IRQ_SPI(43) +#define EXYNOS5_IRQ_RTC_TIC IRQ_SPI(44) +#define EXYNOS5_IRQ_GPIO_XB IRQ_SPI(45) +#define EXYNOS5_IRQ_GPIO_XA IRQ_SPI(46) +#define EXYNOS5_IRQ_GPIO IRQ_SPI(47) +#define EXYNOS5_IRQ_IEM_IEC IRQ_SPI(48) +#define EXYNOS5_IRQ_IEM_APC IRQ_SPI(49) +#define EXYNOS5_IRQ_GPIO_C2C IRQ_SPI(50) #define EXYNOS5_IRQ_UART0 IRQ_SPI(51) #define EXYNOS5_IRQ_UART1 IRQ_SPI(52) #define EXYNOS5_IRQ_UART2 IRQ_SPI(53) #define EXYNOS5_IRQ_UART3 IRQ_SPI(54) #define EXYNOS5_IRQ_UART4 IRQ_SPI(55) +#define EXYNOS5_IRQ_IIC IRQ_SPI(56) +#define EXYNOS5_IRQ_IIC1 IRQ_SPI(57) +#define EXYNOS5_IRQ_IIC2 IRQ_SPI(58) +#define EXYNOS5_IRQ_IIC3 IRQ_SPI(59) +#define EXYNOS5_IRQ_IIC4 IRQ_SPI(60) +#define EXYNOS5_IRQ_IIC5 IRQ_SPI(61) +#define EXYNOS5_IRQ_IIC6 IRQ_SPI(62) +#define EXYNOS5_IRQ_IIC7 IRQ_SPI(63) +#define EXYNOS5_IRQ_IIC_HDMIPHY IRQ_SPI(64) +#define EXYNOS5_IRQ_TMU IRQ_SPI(65) +#define EXYNOS5_IRQ_FIQ_0 IRQ_SPI(66) +#define EXYNOS5_IRQ_FIQ_1 IRQ_SPI(67) +#define EXYNOS5_IRQ_SPI0 IRQ_SPI(68) +#define EXYNOS5_IRQ_SPI1 IRQ_SPI(69) +#define EXYNOS5_IRQ_SPI2 IRQ_SPI(70) +#define EXYNOS5_IRQ_USB_HOST IRQ_SPI(71) +#define EXYNOS5_IRQ_USB3_DRD IRQ_SPI(72) +#define EXYNOS5_IRQ_MIPI_HSI IRQ_SPI(73) +#define EXYNOS5_IRQ_USB_HSOTG IRQ_SPI(74) +#define EXYNOS5_IRQ_HSMMC0 IRQ_SPI(75) +#define EXYNOS5_IRQ_HSMMC1 IRQ_SPI(76) +#define EXYNOS5_IRQ_HSMMC2 IRQ_SPI(77) +#define EXYNOS5_IRQ_HSMMC3 IRQ_SPI(78) +#define EXYNOS5_IRQ_MIPICSI0 IRQ_SPI(79) +#define EXYNOS5_IRQ_MIPICSI1 IRQ_SPI(80) +#define EXYNOS5_IRQ_EFNFCON_DMA_ABORT IRQ_SPI(81) +#define EXYNOS5_IRQ_MIPIDSI0 IRQ_SPI(82) +#define EXYNOS5_IRQ_ROTATOR IRQ_SPI(84) +#define EXYNOS5_IRQ_GSC0 IRQ_SPI(85) +#define EXYNOS5_IRQ_GSC1 IRQ_SPI(86) +#define EXYNOS5_IRQ_GSC2 IRQ_SPI(87) +#define EXYNOS5_IRQ_GSC3 IRQ_SPI(88) +#define EXYNOS5_IRQ_JPEG IRQ_SPI(89) +#define EXYNOS5_IRQ_EFNFCON_DMA IRQ_SPI(90) +#define EXYNOS5_IRQ_2D IRQ_SPI(91) +#define EXYNOS5_IRQ_SFMC0 IRQ_SPI(92) +#define EXYNOS5_IRQ_SFMC1 IRQ_SPI(93) +#define EXYNOS5_IRQ_MIXER IRQ_SPI(94) +#define EXYNOS5_IRQ_HDMI IRQ_SPI(95) +#define EXYNOS5_IRQ_MFC IRQ_SPI(96) +#define EXYNOS5_IRQ_AUDIO_SS IRQ_SPI(97) +#define EXYNOS5_IRQ_I2S0 IRQ_SPI(98) +#define EXYNOS5_IRQ_I2S1 IRQ_SPI(99) +#define EXYNOS5_IRQ_I2S2 IRQ_SPI(100) +#define EXYNOS5_IRQ_AC97 IRQ_SPI(101) +#define EXYNOS5_IRQ_PCM0 IRQ_SPI(102) +#define EXYNOS5_IRQ_PCM1 IRQ_SPI(103) +#define EXYNOS5_IRQ_PCM2 IRQ_SPI(104) +#define EXYNOS5_IRQ_SPDIF IRQ_SPI(105) +#define EXYNOS5_IRQ_ADC0 IRQ_SPI(106) + +#define EXYNOS5_IRQ_SATA_PHY IRQ_SPI(108) +#define EXYNOS5_IRQ_SATA_PMEMREQ IRQ_SPI(109) +#define EXYNOS5_IRQ_CAM_C IRQ_SPI(110) +#define EXYNOS5_IRQ_EAGLE_PMU IRQ_SPI(111) +#define EXYNOS5_IRQ_INTFEEDCTRL_SSS IRQ_SPI(112) +#define EXYNOS5_IRQ_DP1_INTP1 IRQ_SPI(113) +#define EXYNOS5_IRQ_CEC IRQ_SPI(114) +#define EXYNOS5_IRQ_SATA IRQ_SPI(115) +#define EXYNOS5_IRQ_NFCON IRQ_SPI(116) + +#define EXYNOS5_IRQ_MMC44 IRQ_SPI(123) +#define EXYNOS5_IRQ_MDMA1 IRQ_SPI(124) +#define EXYNOS5_IRQ_FIMC_LITE0 IRQ_SPI(125) +#define EXYNOS5_IRQ_FIMC_LITE1 IRQ_SPI(126) +#define EXYNOS5_IRQ_RP_TIMER IRQ_SPI(127) + +#define EXYNOS5_IRQ_PMU COMBINER_IRQ(1, 2) +#define EXYNOS5_IRQ_PMU_CPU1 COMBINER_IRQ(1, 6) + +#define EXYNOS5_IRQ_SYSMMU_GSC0_0 COMBINER_IRQ(2, 0) +#define EXYNOS5_IRQ_SYSMMU_GSC0_1 COMBINER_IRQ(2, 1) +#define EXYNOS5_IRQ_SYSMMU_GSC1_0 COMBINER_IRQ(2, 2) +#define EXYNOS5_IRQ_SYSMMU_GSC1_1 COMBINER_IRQ(2, 3) +#define EXYNOS5_IRQ_SYSMMU_GSC2_0 COMBINER_IRQ(2, 4) +#define EXYNOS5_IRQ_SYSMMU_GSC2_1 COMBINER_IRQ(2, 5) +#define EXYNOS5_IRQ_SYSMMU_GSC3_0 COMBINER_IRQ(2, 6) +#define EXYNOS5_IRQ_SYSMMU_GSC3_1 COMBINER_IRQ(2, 7) + +#define EXYNOS5_IRQ_SYSMMU_FIMD1_0 COMBINER_IRQ(3, 2) +#define EXYNOS5_IRQ_SYSMMU_FIMD1_1 COMBINER_IRQ(3, 3) +#define EXYNOS5_IRQ_SYSMMU_LITE0_0 COMBINER_IRQ(3, 4) +#define EXYNOS5_IRQ_SYSMMU_LITE0_1 COMBINER_IRQ(3, 5) +#define EXYNOS5_IRQ_SYSMMU_SCALERPISP_0 COMBINER_IRQ(3, 6) +#define EXYNOS5_IRQ_SYSMMU_SCALERPISP_1 COMBINER_IRQ(3, 7) + +#define EXYNOS5_IRQ_SYSMMU_ROTATOR_0 COMBINER_IRQ(4, 0) +#define EXYNOS5_IRQ_SYSMMU_ROTATOR_1 COMBINER_IRQ(4, 1) +#define EXYNOS5_IRQ_SYSMMU_JPEG_0 COMBINER_IRQ(4, 2) +#define EXYNOS5_IRQ_SYSMMU_JPEG_1 COMBINER_IRQ(4, 3) + +#define EXYNOS5_IRQ_SYSMMU_FD_0 COMBINER_IRQ(5, 0) +#define EXYNOS5_IRQ_SYSMMU_FD_1 COMBINER_IRQ(5, 1) +#define EXYNOS5_IRQ_SYSMMU_SCALERCISP_0 COMBINER_IRQ(5, 2) +#define EXYNOS5_IRQ_SYSMMU_SCALERCISP_1 COMBINER_IRQ(5, 3) +#define EXYNOS5_IRQ_SYSMMU_MCUISP_0 COMBINER_IRQ(5, 4) +#define EXYNOS5_IRQ_SYSMMU_MCUISP_1 COMBINER_IRQ(5, 5) +#define EXYNOS5_IRQ_SYSMMU_3DNR_0 COMBINER_IRQ(5, 6) +#define EXYNOS5_IRQ_SYSMMU_3DNR_1 COMBINER_IRQ(5, 7) + +#define EXYNOS5_IRQ_SYSMMU_ARM_0 COMBINER_IRQ(6, 0) +#define EXYNOS5_IRQ_SYSMMU_ARM_1 COMBINER_IRQ(6, 1) +#define EXYNOS5_IRQ_SYSMMU_MFC_L_0 COMBINER_IRQ(6, 2) +#define EXYNOS5_IRQ_SYSMMU_MFC_L_1 COMBINER_IRQ(6, 3) +#define EXYNOS5_IRQ_SYSMMU_RTIC_0 COMBINER_IRQ(6, 4) +#define EXYNOS5_IRQ_SYSMMU_RTIC_1 COMBINER_IRQ(6, 5) +#define EXYNOS5_IRQ_SYSMMU_SSS_0 COMBINER_IRQ(6, 6) +#define EXYNOS5_IRQ_SYSMMU_SSS_1 COMBINER_IRQ(6, 7) + +#define EXYNOS5_IRQ_SYSMMU_MDMA0_0 COMBINER_IRQ(7, 0) +#define EXYNOS5_IRQ_SYSMMU_MDMA0_1 COMBINER_IRQ(7, 1) +#define EXYNOS5_IRQ_SYSMMU_MDMA1_0 COMBINER_IRQ(7, 2) +#define EXYNOS5_IRQ_SYSMMU_MDMA1_1 COMBINER_IRQ(7, 3) +#define EXYNOS5_IRQ_SYSMMU_TV_0 COMBINER_IRQ(7, 4) +#define EXYNOS5_IRQ_SYSMMU_TV_1 COMBINER_IRQ(7, 5) +#define EXYNOS5_IRQ_SYSMMU_GPSX_0 COMBINER_IRQ(7, 6) +#define EXYNOS5_IRQ_SYSMMU_GPSX_1 COMBINER_IRQ(7, 7) + +#define EXYNOS5_IRQ_SYSMMU_MFC_R_0 COMBINER_IRQ(8, 5) +#define EXYNOS5_IRQ_SYSMMU_MFC_R_1 COMBINER_IRQ(8, 6) + +#define EXYNOS5_IRQ_SYSMMU_DIS1_0 COMBINER_IRQ(9, 4) +#define EXYNOS5_IRQ_SYSMMU_DIS1_1 COMBINER_IRQ(9, 5) + +#define EXYNOS5_IRQ_DP COMBINER_IRQ(10, 3) +#define EXYNOS5_IRQ_SYSMMU_DIS0_0 COMBINER_IRQ(10, 4) +#define EXYNOS5_IRQ_SYSMMU_DIS0_1 COMBINER_IRQ(10, 5) +#define EXYNOS5_IRQ_SYSMMU_ISP_0 COMBINER_IRQ(10, 6) +#define EXYNOS5_IRQ_SYSMMU_ISP_1 COMBINER_IRQ(10, 7) + +#define EXYNOS5_IRQ_SYSMMU_ODC_0 COMBINER_IRQ(11, 0) +#define EXYNOS5_IRQ_SYSMMU_ODC_1 COMBINER_IRQ(11, 1) +#define EXYNOS5_IRQ_SYSMMU_DRC_0 COMBINER_IRQ(11, 6) +#define EXYNOS5_IRQ_SYSMMU_DRC_1 COMBINER_IRQ(11, 7) + +#define EXYNOS5_IRQ_FIMD1_FIFO COMBINER_IRQ(18, 4) +#define EXYNOS5_IRQ_FIMD1_VSYNC COMBINER_IRQ(18, 5) +#define EXYNOS5_IRQ_FIMD1_SYSTEM COMBINER_IRQ(18, 6) + +#define EXYNOS5_IRQ_EINT0 COMBINER_IRQ(23, 0) +#define EXYNOS5_IRQ_MCT_L0 COMBINER_IRQ(23, 1) +#define EXYNOS5_IRQ_MCT_L1 COMBINER_IRQ(23, 2) +#define EXYNOS5_IRQ_MCT_G0 COMBINER_IRQ(23, 3) +#define EXYNOS5_IRQ_MCT_G1 COMBINER_IRQ(23, 4) +#define EXYNOS5_IRQ_MCT_G2 COMBINER_IRQ(23, 5) +#define EXYNOS5_IRQ_MCT_G3 COMBINER_IRQ(23, 6) + +#define EXYNOS5_IRQ_EINT1 COMBINER_IRQ(24, 0) +#define EXYNOS5_IRQ_SYSMMU_LITE1_0 COMBINER_IRQ(24, 1) +#define EXYNOS5_IRQ_SYSMMU_LITE1_1 COMBINER_IRQ(24, 2) +#define EXYNOS5_IRQ_SYSMMU_2D_0 COMBINER_IRQ(24, 5) +#define EXYNOS5_IRQ_SYSMMU_2D_1 COMBINER_IRQ(24, 6) + +#define EXYNOS5_IRQ_EINT2 COMBINER_IRQ(25, 0) +#define EXYNOS5_IRQ_EINT3 COMBINER_IRQ(25, 1) + +#define EXYNOS5_IRQ_EINT4 COMBINER_IRQ(26, 0) +#define EXYNOS5_IRQ_EINT5 COMBINER_IRQ(26, 1) + +#define EXYNOS5_IRQ_EINT6 COMBINER_IRQ(27, 0) +#define EXYNOS5_IRQ_EINT7 COMBINER_IRQ(27, 1) + +#define EXYNOS5_IRQ_EINT8 COMBINER_IRQ(28, 0) +#define EXYNOS5_IRQ_EINT9 COMBINER_IRQ(28, 1) + +#define EXYNOS5_IRQ_EINT10 COMBINER_IRQ(29, 0) +#define EXYNOS5_IRQ_EINT11 COMBINER_IRQ(29, 1) + +#define EXYNOS5_IRQ_EINT12 COMBINER_IRQ(30, 0) +#define EXYNOS5_IRQ_EINT13 COMBINER_IRQ(30, 1) + +#define EXYNOS5_IRQ_EINT14 COMBINER_IRQ(31, 0) +#define EXYNOS5_IRQ_EINT15 COMBINER_IRQ(31, 1) + +#define EXYNOS5_MAX_COMBINER_NR 32 + +#define EXYNOS5_IRQ_GPIO1_NR_GROUPS 13 +#define EXYNOS5_IRQ_GPIO2_NR_GROUPS 9 +#define EXYNOS5_IRQ_GPIO3_NR_GROUPS 5 +#define EXYNOS5_IRQ_GPIO4_NR_GROUPS 1 + +#define MAX_COMBINER_NR (EXYNOS4_MAX_COMBINER_NR > EXYNOS5_MAX_COMBINER_NR ? \ + EXYNOS4_MAX_COMBINER_NR : EXYNOS5_MAX_COMBINER_NR) + +#define S5P_EINT_BASE1 COMBINER_IRQ(MAX_COMBINER_NR, 0) +#define S5P_EINT_BASE2 (S5P_EINT_BASE1 + 16) +#define S5P_GPIOINT_BASE (S5P_EINT_BASE1 + 32) +#define IRQ_GPIO_END (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT) +#define IRQ_TIMER_BASE (IRQ_GPIO_END + 64) + +/* Set the default NR_IRQS */ + +#define NR_IRQS (IRQ_TIMER_BASE + IRQ_TIMER_COUNT) #endif /* __ASM_ARCH_IRQS_H */ diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index 85b5527..1016515 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c @@ -258,7 +258,10 @@ static void exynos4_clockevent_init(void) mct_comp_device.cpumask = cpumask_of(0); clockevents_register_device(&mct_comp_device); - setup_irq(IRQ_MCT_G0, &mct_comp_event_irq); + if (soc_is_exynos5250()) + setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq); + else + setup_irq(EXYNOS4_IRQ_MCT_G0, &mct_comp_event_irq); } #ifdef CONFIG_LOCAL_TIMERS @@ -406,16 +409,16 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt) if (mct_int_type == MCT_INT_SPI) { if (cpu == 0) { mct_tick0_event_irq.dev_id = mevt; - evt->irq = IRQ_MCT_L0; - setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq); + evt->irq = EXYNOS4_IRQ_MCT_L0; + setup_irq(EXYNOS4_IRQ_MCT_L0, &mct_tick0_event_irq); } else { mct_tick1_event_irq.dev_id = mevt; - evt->irq = IRQ_MCT_L1; - setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq); - irq_set_affinity(IRQ_MCT_L1, cpumask_of(1)); + evt->irq = EXYNOS4_IRQ_MCT_L1; + setup_irq(EXYNOS4_IRQ_MCT_L1, &mct_tick1_event_irq); + irq_set_affinity(EXYNOS4_IRQ_MCT_L1, cpumask_of(1)); } } else { - enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0); + enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0); } } @@ -437,7 +440,7 @@ void local_timer_stop(struct clock_event_device *evt) else remove_irq(evt->irq, &mct_tick1_event_irq); else - disable_percpu_irq(IRQ_MCT_LOCALTIMER); + disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER); } #endif /* CONFIG_LOCAL_TIMERS */ @@ -452,11 +455,11 @@ static void __init exynos4_timer_resources(void) if (mct_int_type == MCT_INT_PPI) { int err; - err = request_percpu_irq(IRQ_MCT_LOCALTIMER, + err = request_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, exynos4_mct_tick_isr, "MCT", &percpu_mct_tick); WARN(err, "MCT: can't request IRQ %d (%d)\n", - IRQ_MCT_LOCALTIMER, err); + EXYNOS_IRQ_MCT_LOCALTIMER, err); } #endif /* CONFIG_LOCAL_TIMERS */ } diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c index 327acb3..d1bfeca 100644 --- a/arch/arm/plat-s5p/irq-pm.c +++ b/arch/arm/plat-s5p/irq-pm.c @@ -39,19 +39,32 @@ unsigned long s3c_irqwake_eintallow = 0xffffffffL; int s3c_irq_wake(struct irq_data *data, unsigned int state) { unsigned long irqbit; + unsigned int irq_rtc_tic, irq_rtc_alarm; + +#ifdef CONFIG_ARCH_EXYNOS + if (soc_is_exynos5250()) { + irq_rtc_tic = EXYNOS5_IRQ_RTC_TIC; + irq_rtc_alarm = EXYNOS5_IRQ_RTC_ALARM; + } else { + irq_rtc_tic = EXYNOS4_IRQ_RTC_TIC; + irq_rtc_alarm = EXYNOS4_IRQ_RTC_ALARM; + } +#else + irq_rtc_tic = IRQ_RTC_TIC; + irq_rtc_alarm = IRQ_RTC_ALARM; +#endif + + if (data->irq == irq_rtc_tic || data->irq == irq_rtc_alarm) { + irqbit = 1 << (data->irq + 1 - irq_rtc_alarm); - switch (data->irq) { - case IRQ_RTC_TIC: - case IRQ_RTC_ALARM: - irqbit = 1 << (data->irq + 1 - IRQ_RTC_ALARM); if (!state) s3c_irqwake_intmask |= irqbit; else s3c_irqwake_intmask &= ~irqbit; - break; - default: + } else { return -ENOENT; } + return 0; } diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c index 51583cd..f980cf3 100644 --- a/arch/arm/plat-samsung/irq-vic-timer.c +++ b/arch/arm/plat-samsung/irq-vic-timer.c @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -57,6 +58,21 @@ void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq) struct irq_chip_type *ct; unsigned int i; +#ifdef CONFIG_ARCH_EXYNOS + if (soc_is_exynos5250()) { + pirq[0] = EXYNOS5_IRQ_TIMER0_VIC; + pirq[1] = EXYNOS5_IRQ_TIMER1_VIC; + pirq[2] = EXYNOS5_IRQ_TIMER2_VIC; + pirq[3] = EXYNOS5_IRQ_TIMER3_VIC; + pirq[4] = EXYNOS5_IRQ_TIMER4_VIC; + } else { + pirq[0] = EXYNOS4_IRQ_TIMER0_VIC; + pirq[1] = EXYNOS4_IRQ_TIMER1_VIC; + pirq[2] = EXYNOS4_IRQ_TIMER2_VIC; + pirq[3] = EXYNOS4_IRQ_TIMER3_VIC; + pirq[4] = EXYNOS4_IRQ_TIMER4_VIC; + } +#endif s3c_tgc = irq_alloc_generic_chip("s3c-timer", 1, timer_irq, S3C64XX_TINT_CSTAT, handle_level_irq); -- cgit v0.10.2 From 330c90a54c82596dfe355163c4d888e51a0fe65b Mon Sep 17 00:00:00 2001 From: Eunki Kim Date: Wed, 14 Mar 2012 01:43:31 -0700 Subject: ARM: EXYNOS: support EINT for EXYNOS4 and EXYNOS5 The GPIOs of EXYNOS4 and EXYNOS5 are changed to use ioremap instead of static mapping. It alse causes the change of external interrupt IO mapping. This patch changes EXYNOS4 to EXYNOS for common use and changes EINT_x macros for supporting dynamic IO mapping. Signed-off-by: Eunki Kim Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 4ef0cb5..cbbaca5 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -665,10 +665,60 @@ static void __init exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no) s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no); } +static void __iomem *exynos_eint_base; + static DEFINE_SPINLOCK(eint_lock); static unsigned int eint0_15_data[16]; +static inline int exynos4_irq_to_gpio(unsigned int irq) +{ + if (irq < IRQ_EINT(0)) + return -EINVAL; + + irq -= IRQ_EINT(0); + if (irq < 8) + return EXYNOS4_GPX0(irq); + + irq -= 8; + if (irq < 8) + return EXYNOS4_GPX1(irq); + + irq -= 8; + if (irq < 8) + return EXYNOS4_GPX2(irq); + + irq -= 8; + if (irq < 8) + return EXYNOS4_GPX3(irq); + + return -EINVAL; +} + +static inline int exynos5_irq_to_gpio(unsigned int irq) +{ + if (irq < IRQ_EINT(0)) + return -EINVAL; + + irq -= IRQ_EINT(0); + if (irq < 8) + return EXYNOS5_GPX0(irq); + + irq -= 8; + if (irq < 8) + return EXYNOS5_GPX1(irq); + + irq -= 8; + if (irq < 8) + return EXYNOS5_GPX2(irq); + + irq -= 8; + if (irq < 8) + return EXYNOS5_GPX3(irq); + + return -EINVAL; +} + static unsigned int exynos4_eint0_15_src_int[16] = { EXYNOS4_IRQ_EINT0, EXYNOS4_IRQ_EINT1, @@ -706,41 +756,41 @@ static unsigned int exynos5_eint0_15_src_int[16] = { EXYNOS5_IRQ_EINT14, EXYNOS5_IRQ_EINT15, }; -static inline void exynos4_irq_eint_mask(struct irq_data *data) +static inline void exynos_irq_eint_mask(struct irq_data *data) { u32 mask; spin_lock(&eint_lock); - mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); - mask |= eint_irq_to_bit(data->irq); - __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); + mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq)); + mask |= EINT_OFFSET_BIT(data->irq); + __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq)); spin_unlock(&eint_lock); } -static void exynos4_irq_eint_unmask(struct irq_data *data) +static void exynos_irq_eint_unmask(struct irq_data *data) { u32 mask; spin_lock(&eint_lock); - mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); - mask &= ~(eint_irq_to_bit(data->irq)); - __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); + mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq)); + mask &= ~(EINT_OFFSET_BIT(data->irq)); + __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq)); spin_unlock(&eint_lock); } -static inline void exynos4_irq_eint_ack(struct irq_data *data) +static inline void exynos_irq_eint_ack(struct irq_data *data) { - __raw_writel(eint_irq_to_bit(data->irq), - S5P_EINT_PEND(EINT_REG_NR(data->irq))); + __raw_writel(EINT_OFFSET_BIT(data->irq), + EINT_PEND(exynos_eint_base, data->irq)); } -static void exynos4_irq_eint_maskack(struct irq_data *data) +static void exynos_irq_eint_maskack(struct irq_data *data) { - exynos4_irq_eint_mask(data); - exynos4_irq_eint_ack(data); + exynos_irq_eint_mask(data); + exynos_irq_eint_ack(data); } -static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type) +static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type) { int offs = EINT_OFFSET(data->irq); int shift; @@ -777,39 +827,27 @@ static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type) mask = 0x7 << shift; spin_lock(&eint_lock); - ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq))); + ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->irq)); ctrl &= ~mask; ctrl |= newvalue << shift; - __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq))); + __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->irq)); spin_unlock(&eint_lock); - switch (offs) { - case 0 ... 7: - s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE); - break; - case 8 ... 15: - s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE); - break; - case 16 ... 23: - s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE); - break; - case 24 ... 31: - s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE); - break; - default: - printk(KERN_ERR "No such irq number %d", offs); - } + if (soc_is_exynos5250()) + s3c_gpio_cfgpin(exynos5_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf)); + else + s3c_gpio_cfgpin(exynos4_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf)); return 0; } -static struct irq_chip exynos4_irq_eint = { - .name = "exynos4-eint", - .irq_mask = exynos4_irq_eint_mask, - .irq_unmask = exynos4_irq_eint_unmask, - .irq_mask_ack = exynos4_irq_eint_maskack, - .irq_ack = exynos4_irq_eint_ack, - .irq_set_type = exynos4_irq_eint_set_type, +static struct irq_chip exynos_irq_eint = { + .name = "exynos-eint", + .irq_mask = exynos_irq_eint_mask, + .irq_unmask = exynos_irq_eint_unmask, + .irq_mask_ack = exynos_irq_eint_maskack, + .irq_ack = exynos_irq_eint_ack, + .irq_set_type = exynos_irq_eint_set_type, #ifdef CONFIG_PM .irq_set_wake = s3c_irqext_wake, #endif @@ -824,12 +862,12 @@ static struct irq_chip exynos4_irq_eint = { * * Each EINT pend/mask registers handle eight of them. */ -static inline void exynos4_irq_demux_eint(unsigned int start) +static inline void exynos_irq_demux_eint(unsigned int start) { unsigned int irq; - u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start))); - u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start))); + u32 status = __raw_readl(EINT_PEND(exynos_eint_base, start)); + u32 mask = __raw_readl(EINT_MASK(exynos_eint_base, start)); status &= ~mask; status &= 0xff; @@ -841,12 +879,12 @@ static inline void exynos4_irq_demux_eint(unsigned int start) } } -static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) +static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) { struct irq_chip *chip = irq_get_chip(irq); chained_irq_enter(chip, desc); - exynos4_irq_demux_eint(IRQ_EINT(16)); - exynos4_irq_demux_eint(IRQ_EINT(24)); + exynos_irq_demux_eint(IRQ_EINT(16)); + exynos_irq_demux_eint(IRQ_EINT(24)); chained_irq_exit(chip, desc); } @@ -867,20 +905,27 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) chained_irq_exit(chip, desc); } -static int __init exynos4_init_irq_eint(void) +static int __init exynos_init_irq_eint(void) { int irq; if (soc_is_exynos5250()) - return 0; + exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K); + else + exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K); + + if (exynos_eint_base == NULL) { + pr_err("unable to ioremap for EINT base address\n"); + return -ENOMEM; + } for (irq = 0 ; irq <= 31 ; irq++) { - irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint, + irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint, handle_level_irq); set_irq_flags(IRQ_EINT(irq), IRQF_VALID); } - irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos4_irq_demux_eint16_31); + irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31); for (irq = 0 ; irq <= 15 ; irq++) { eint0_15_data[irq] = IRQ_EINT(irq); @@ -900,4 +945,4 @@ static int __init exynos4_init_irq_eint(void) return 0; } -arch_initcall(exynos4_init_irq_eint); +arch_initcall(exynos_init_irq_eint); diff --git a/arch/arm/mach-exynos/include/mach/regs-gpio.h b/arch/arm/mach-exynos/include/mach/regs-gpio.h index 1401b21..e4b5b60 100644 --- a/arch/arm/mach-exynos/include/mach/regs-gpio.h +++ b/arch/arm/mach-exynos/include/mach/regs-gpio.h @@ -16,6 +16,15 @@ #include #include +#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3) +#define EINT_CON(b, x) (b + 0xE00 + (EINT_REG_NR(x) * 4)) +#define EINT_FLTCON(b, x) (b + 0xE80 + (EINT_REG_NR(x) * 4)) +#define EINT_MASK(b, x) (b + 0xF00 + (EINT_REG_NR(x) * 4)) +#define EINT_PEND(b, x) (b + 0xF40 + (EINT_REG_NR(x) * 4)) + +#define EINT_OFFSET_BIT(x) (1 << (EINT_OFFSET(x) & 0x7)) + +/* compatibility for plat-s5p/irq-pm.c */ #define EXYNOS4_EINT40CON (S5P_VA_GPIO2 + 0xE00) #define S5P_EINT_CON(x) (EXYNOS4_EINT40CON + ((x) * 0x4)) @@ -28,15 +37,4 @@ #define EXYNOS4_EINT40PEND (S5P_VA_GPIO2 + 0xF40) #define S5P_EINT_PEND(x) (EXYNOS4_EINT40PEND + ((x) * 0x4)) -#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3) - -#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7)) - -#define EINT_MODE S3C_GPIO_SFN(0xf) - -#define EINT_GPIO_0(x) EXYNOS4_GPX0(x) -#define EINT_GPIO_1(x) EXYNOS4_GPX1(x) -#define EINT_GPIO_2(x) EXYNOS4_GPX2(x) -#define EINT_GPIO_3(x) EXYNOS4_GPX3(x) - #endif /* __ASM_ARCH_REGS_GPIO_H */ -- cgit v0.10.2 From e9bba61522a7650b0e4d9952bb3ece81d473a52c Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Wed, 25 Jan 2012 15:35:57 +0900 Subject: ARM: EXYNOS: add support get_core_count() for EXYNOS5250 The EXYNOS5250 has two Cortex-A15 cores and there's no need to call scu_enable() in platform_smp_prepare_cpus() because Cortex-A15 has no regarding scu register which can be used for getting number of cores. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 0f2035a..36c3984 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -166,7 +166,10 @@ void __init smp_init_cpus(void) void __iomem *scu_base = scu_base_addr(); unsigned int i, ncores; - ncores = scu_base ? scu_get_core_count(scu_base) : 1; + if (soc_is_exynos5250()) + ncores = 2; + else + ncores = scu_base ? scu_get_core_count(scu_base) : 1; /* sanity check */ if (ncores > nr_cpu_ids) { @@ -183,8 +186,8 @@ void __init smp_init_cpus(void) void __init platform_smp_prepare_cpus(unsigned int max_cpus) { - - scu_enable(scu_base_addr()); + if (!soc_is_exynos5250()) + scu_enable(scu_base_addr()); /* * Write the address of secondary startup into the -- cgit v0.10.2 From 23f16c7b7cb6a5d086254cbf997c13a56c05031e Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Tue, 13 Mar 2012 07:44:39 -0700 Subject: ARM: EXYNOS: add support ARCH_EXYNOS5 for EXYNOS5 SoCs This patch adds CONFIG_ARCH_EXYNOS5 and CONFIG_SOC_EXYNOS5250 for supporting EXYNOS5250 SoC and allows supporting EXYNOS4 and EXYNOS5 together. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 5e0a456..a2ed05c 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -11,18 +11,19 @@ if ARCH_EXYNOS menu "SAMSUNG EXYNOS SoCs Support" -choice - prompt "EXYNOS System Type" - default ARCH_EXYNOS4 - config ARCH_EXYNOS4 bool "SAMSUNG EXYNOS4" + default y select HAVE_SMP select MIGHT_HAVE_CACHE_L2X0 help Samsung EXYNOS4 SoCs based systems -endchoice +config ARCH_EXYNOS5 + bool "SAMSUNG EXYNOS5" + select HAVE_SMP + help + Samsung EXYNOS5 (Cortex-A15) SoC based systems comment "EXYNOS SoCs" @@ -55,6 +56,13 @@ config SOC_EXYNOS4412 help Enable EXYNOS4412 SoC support +config SOC_EXYNOS5250 + bool "SAMSUNG EXYNOS5250" + default y + depends on ARCH_EXYNOS5 + help + Enable EXYNOS5250 SoC support + config EXYNOS4_MCT bool default y diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index f8a3770..7214092 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -14,6 +14,7 @@ obj- := obj-$(CONFIG_ARCH_EXYNOS) += common.o obj-$(CONFIG_ARCH_EXYNOS4) += clock-exynos4.o +obj-$(CONFIG_ARCH_EXYNOS5) += clock-exynos5.o obj-$(CONFIG_CPU_EXYNOS4210) += clock-exynos4210.o obj-$(CONFIG_SOC_EXYNOS4212) += clock-exynos4212.o -- cgit v0.10.2 From b3e68fb17a25ffa73610a21bf3974b7297026a0f Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Fri, 10 Feb 2012 13:13:15 +0900 Subject: ARM: EXYNOS: add support device tree enabled board file for EXYNOS5 This patch adds a new EXYNOS5 compatible device tree enabled board When using this, a corresponding device tree blob which describes the board's properties should be supplied at boot time to the kernel. Cc: Thomas Abraham Cc: Grant Likely Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index a2ed05c..42f072db 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -362,7 +362,7 @@ config MACH_SMDK4412 Machine support for Samsung SMDK4412 endif -comment "Flattened Device Tree based board for Exynos4 based SoC" +comment "Flattened Device Tree based board for EXYNOS SoCs" config MACH_EXYNOS4_DT bool "Samsung Exynos4 Machine using device tree" @@ -376,6 +376,15 @@ config MACH_EXYNOS4_DT Note: This is under development and not all peripherals can be supported with this machine file. +config MACH_EXYNOS5_DT + bool "SAMSUNG EXYNOS5 Machine using device tree" + select SOC_EXYNOS5250 + select USE_OF + select ARM_AMBA + help + Machine support for Samsung Exynos4 machine with device tree enabled. + Select this if a fdt blob is available for the EXYNOS4 SoC based board. + if ARCH_EXYNOS4 comment "Configuration for HSMMC 8-bit bus width" diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 7214092..29967ef 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_MACH_SMDK4212) += mach-smdk4x12.o obj-$(CONFIG_MACH_SMDK4412) += mach-smdk4x12.o obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o +obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o # device support diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c new file mode 100644 index 0000000..0d26f50 --- /dev/null +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c @@ -0,0 +1,78 @@ +/* + * SAMSUNG EXYNOS5250 Flattened Device Tree enabled machine + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include + +#include +#include +#include + +#include +#include + +#include "common.h" + +/* + * The following lookup table is used to override device names when devices + * are registered from device tree. This is temporarily added to enable + * device tree support addition for the EXYNOS5 architecture. + * + * For drivers that require platform data to be provided from the machine + * file, a platform data pointer can also be supplied along with the + * devices names. Usually, the platform data elements that cannot be parsed + * from the device tree by the drivers (example: function pointers) are + * supplied. But it should be noted that this is a temporary mechanism and + * at some point, the drivers should be capable of parsing all the platform + * data from the device tree. + */ +static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = { + OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART0, + "exynos4210-uart.0", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART1, + "exynos4210-uart.1", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART2, + "exynos4210-uart.2", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART3, + "exynos4210-uart.3", NULL), + OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL), + OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL), + OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.2", NULL), + {}, +}; + +static void __init exynos5250_dt_map_io(void) +{ + exynos_init_io(NULL, 0); + s3c24xx_init_clocks(24000000); +} + +static void __init exynos5250_dt_machine_init(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, + exynos5250_auxdata_lookup, NULL); +} + +static char const *exynos5250_dt_compat[] __initdata = { + "samsung,exynos5250", + NULL +}; + +DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)") + /* Maintainer: Kukjin Kim */ + .init_irq = exynos5_init_irq, + .map_io = exynos5250_dt_map_io, + .handle_irq = gic_handle_irq, + .init_machine = exynos5250_dt_machine_init, + .timer = &exynos4_timer, + .dt_compat = exynos5250_dt_compat, + .restart = exynos5_restart, +MACHINE_END -- cgit v0.10.2 From b074abb719714a9efd0918ba48554c3f734403e8 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Fri, 10 Feb 2012 13:12:21 +0900 Subject: ARM: dts: add initial dts file for EXYNOS5250, SMDK5250 This patch adds initial dts file for EXYNOS5250 SoC. This dts file is including the SoC specific devices and properties. And adds the dts file for SMDK5250 board which uses the EXYNOS5250 dts file. Its board specific properites will be added later. Cc: Thomas Abraham Cc: Grant Likely Signed-off-by: Kukjin Kim diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts new file mode 100644 index 0000000..399d17b --- /dev/null +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -0,0 +1,26 @@ +/* + * SAMSUNG SMDK5250 board device tree source + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/dts-v1/; +/include/ "exynos5250.dtsi" + +/ { + model = "SAMSUNG SMDK5250 board based on EXYNOS5250"; + compatible = "samsung,smdk5250", "samsung,exynos5250"; + + memory { + reg = <0x40000000 0x80000000>; + }; + + chosen { + bootargs = "root=/dev/ram0 rw ramdisk=8192 console=ttySAC1,115200"; + }; +}; diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi new file mode 100644 index 0000000..dfc4335 --- /dev/null +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -0,0 +1,413 @@ +/* + * SAMSUNG EXYNOS5250 SoC device tree source + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * SAMSUNG EXYNOS5250 SoC device nodes are listed in this file. + * EXYNOS5250 based board files can include this file and provide + * values for board specfic bindings. + * + * Note: This file does not include device nodes for all the controllers in + * EXYNOS5250 SoC. As device tree coverage for EXYNOS5250 increases, + * additional nodes can be added to this file. + * + * 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/ "skeleton.dtsi" + +/ { + compatible = "samsung,exynos5250"; + interrupt-parent = <&gic>; + + gic:interrupt-controller@10490000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x10490000 0x1000>, <0x10480000 0x100>; + }; + + watchdog { + compatible = "samsung,s3c2410-wdt"; + reg = <0x101D0000 0x100>; + interrupts = <0 42 0>; + }; + + rtc { + compatible = "samsung,s3c6410-rtc"; + reg = <0x101E0000 0x100>; + interrupts = <0 43 0>, <0 44 0>; + }; + + sdhci@12200000 { + compatible = "samsung,exynos4210-sdhci"; + reg = <0x12200000 0x100>; + interrupts = <0 75 0>; + }; + + sdhci@12210000 { + compatible = "samsung,exynos4210-sdhci"; + reg = <0x12210000 0x100>; + interrupts = <0 76 0>; + }; + + sdhci@12220000 { + compatible = "samsung,exynos4210-sdhci"; + reg = <0x12220000 0x100>; + interrupts = <0 77 0>; + }; + + sdhci@12230000 { + compatible = "samsung,exynos4210-sdhci"; + reg = <0x12230000 0x100>; + interrupts = <0 78 0>; + }; + + serial@12C00000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x12C00000 0x100>; + interrupts = <0 51 0>; + }; + + serial@12C10000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x12C10000 0x100>; + interrupts = <0 52 0>; + }; + + serial@12C20000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x12C20000 0x100>; + interrupts = <0 53 0>; + }; + + serial@12C30000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x12C30000 0x100>; + interrupts = <0 54 0>; + }; + + i2c@12C60000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x12C60000 0x100>; + interrupts = <0 56 0>; + }; + + i2c@12C70000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x12C70000 0x100>; + interrupts = <0 57 0>; + }; + + i2c@12C80000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x12C80000 0x100>; + interrupts = <0 58 0>; + }; + + i2c@12C90000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x12C90000 0x100>; + interrupts = <0 59 0>; + }; + + i2c@12CA0000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x12CA0000 0x100>; + interrupts = <0 60 0>; + }; + + i2c@12CB0000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x12CB0000 0x100>; + interrupts = <0 61 0>; + }; + + i2c@12CC0000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x12CC0000 0x100>; + interrupts = <0 62 0>; + }; + + i2c@12CD0000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x12CD0000 0x100>; + interrupts = <0 63 0>; + }; + + amba { + #address-cells = <1>; + #size-cells = <1>; + compatible = "arm,amba-bus"; + interrupt-parent = <&gic>; + ranges; + + pdma0: pdma@121A0000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x121A0000 0x1000>; + interrupts = <0 34 0>; + }; + + pdma1: pdma@121B0000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x121B0000 0x1000>; + interrupts = <0 35 0>; + }; + + mdma0: pdma@10800000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x10800000 0x1000>; + interrupts = <0 33 0>; + }; + + mdma1: pdma@11C10000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x11C10000 0x1000>; + interrupts = <0 124 0>; + }; + }; + + gpio-controllers { + #address-cells = <1>; + #size-cells = <1>; + gpio-controller; + ranges; + + gpa0: gpio-controller@11400000 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400000 0x20>; + #gpio-cells = <4>; + }; + + gpa1: gpio-controller@11400020 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400020 0x20>; + #gpio-cells = <4>; + }; + + gpa2: gpio-controller@11400040 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400040 0x20>; + #gpio-cells = <4>; + }; + + gpb0: gpio-controller@11400060 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400060 0x20>; + #gpio-cells = <4>; + }; + + gpb1: gpio-controller@11400080 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400080 0x20>; + #gpio-cells = <4>; + }; + + gpb2: gpio-controller@114000A0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114000A0 0x20>; + #gpio-cells = <4>; + }; + + gpb3: gpio-controller@114000C0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114000C0 0x20>; + #gpio-cells = <4>; + }; + + gpc0: gpio-controller@114000E0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114000E0 0x20>; + #gpio-cells = <4>; + }; + + gpc1: gpio-controller@11400100 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400100 0x20>; + #gpio-cells = <4>; + }; + + gpc2: gpio-controller@11400120 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400120 0x20>; + #gpio-cells = <4>; + }; + + gpc3: gpio-controller@11400140 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400140 0x20>; + #gpio-cells = <4>; + }; + + gpd0: gpio-controller@11400160 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400160 0x20>; + #gpio-cells = <4>; + }; + + gpd1: gpio-controller@11400180 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400180 0x20>; + #gpio-cells = <4>; + }; + + gpy0: gpio-controller@114001A0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114001A0 0x20>; + #gpio-cells = <4>; + }; + + gpy1: gpio-controller@114001C0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114001C0 0x20>; + #gpio-cells = <4>; + }; + + gpy2: gpio-controller@114001E0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114001E0 0x20>; + #gpio-cells = <4>; + }; + + gpy3: gpio-controller@11400200 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400200 0x20>; + #gpio-cells = <4>; + }; + + gpy4: gpio-controller@11400220 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400220 0x20>; + #gpio-cells = <4>; + }; + + gpy5: gpio-controller@11400240 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400240 0x20>; + #gpio-cells = <4>; + }; + + gpy6: gpio-controller@11400260 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400260 0x20>; + #gpio-cells = <4>; + }; + + gpx0: gpio-controller@11400C00 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400C00 0x20>; + #gpio-cells = <4>; + }; + + gpx1: gpio-controller@11400C20 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400C20 0x20>; + #gpio-cells = <4>; + }; + + gpx2: gpio-controller@11400C40 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400C40 0x20>; + #gpio-cells = <4>; + }; + + gpx3: gpio-controller@11400C60 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400C60 0x20>; + #gpio-cells = <4>; + }; + + gpe0: gpio-controller@13400000 { + compatible = "samsung,exynos4-gpio"; + reg = <0x13400000 0x20>; + #gpio-cells = <4>; + }; + + gpe1: gpio-controller@13400020 { + compatible = "samsung,exynos4-gpio"; + reg = <0x13400020 0x20>; + #gpio-cells = <4>; + }; + + gpf0: gpio-controller@13400040 { + compatible = "samsung,exynos4-gpio"; + reg = <0x13400040 0x20>; + #gpio-cells = <4>; + }; + + gpf1: gpio-controller@13400060 { + compatible = "samsung,exynos4-gpio"; + reg = <0x13400060 0x20>; + #gpio-cells = <4>; + }; + + gpg0: gpio-controller@13400080 { + compatible = "samsung,exynos4-gpio"; + reg = <0x13400080 0x20>; + #gpio-cells = <4>; + }; + + gpg1: gpio-controller@134000A0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x134000A0 0x20>; + #gpio-cells = <4>; + }; + + gpg2: gpio-controller@134000C0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x134000C0 0x20>; + #gpio-cells = <4>; + }; + + gph0: gpio-controller@134000E0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x134000E0 0x20>; + #gpio-cells = <4>; + }; + + gph1: gpio-controller@13400100 { + compatible = "samsung,exynos4-gpio"; + reg = <0x13400100 0x20>; + #gpio-cells = <4>; + }; + + gpv0: gpio-controller@10D10000 { + compatible = "samsung,exynos4-gpio"; + reg = <0x10D10000 0x20>; + #gpio-cells = <4>; + }; + + gpv1: gpio-controller@10D10020 { + compatible = "samsung,exynos4-gpio"; + reg = <0x10D10020 0x20>; + #gpio-cells = <4>; + }; + + gpv2: gpio-controller@10D10040 { + compatible = "samsung,exynos4-gpio"; + reg = <0x10D10040 0x20>; + #gpio-cells = <4>; + }; + + gpv3: gpio-controller@10D10060 { + compatible = "samsung,exynos4-gpio"; + reg = <0x10D10060 0x20>; + #gpio-cells = <4>; + }; + + gpv4: gpio-controller@10D10080 { + compatible = "samsung,exynos4-gpio"; + reg = <0x10D10080 0x20>; + #gpio-cells = <4>; + }; + + gpz: gpio-controller@03860000 { + compatible = "samsung,exynos4-gpio"; + reg = <0x03860000 0x20>; + #gpio-cells = <4>; + }; + }; +}; -- cgit v0.10.2 From efd5af0dc988bd3498065c91f6332545de7ea999 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Wed, 7 Mar 2012 05:14:07 -0800 Subject: ARM: EXYNOS: Fix compilation error with mach-exynos4-dt board Commit 171c067 ("ARM: EXYNOS: add support uart for EXYNOS4 and EXYNOS5") renames S5P_PA_UARTn to EXYNOS4_PA_UARTn. Hence we need to do similar modification in mach-exynos4-dt.c to fix compilation error. arch/arm/mach-exynos/mach-exynos4-dt.c:40:2: error: 'S5P_PA_UART0' undeclared here (not in a function) Signed-off-by: Tushar Behera Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index e6b02fd..8245f1c 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -37,13 +37,13 @@ * data from the device tree. */ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = { - OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART0, + OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART0, "exynos4210-uart.0", NULL), - OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART1, + OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART1, "exynos4210-uart.1", NULL), - OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART2, + OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART2, "exynos4210-uart.2", NULL), - OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART3, + OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART3, "exynos4210-uart.3", NULL), OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(0), "exynos4-sdhci.0", NULL), -- cgit v0.10.2 From e9dd7ed2a365b021cdbb35b5cad62f6ab6aeb5d2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Mar 2012 18:55:23 -0700 Subject: ARM: mach-shmobile: ap4evb: Reserve DMA memory for the frame buffer ap4evb board needs the same fix as 1740d3448012475f6b63172631c60cbcd1994a81 (ARM: mach-shmobile: mackerel: Reserve DMA memory for the frame buffer) Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index b4718b0..6e3fab6 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -1206,6 +1206,12 @@ static void __init ap4evb_map_io(void) { iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc)); + /* + * DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't + * enough to allocate the frame buffer memory. + */ + init_consistent_dma_size(12 << 20); + /* setup early devices and console here as well */ sh7372_add_early_devices(); shmobile_setup_console(); -- cgit v0.10.2