diff options
Diffstat (limited to 'arch/arm/mach-omap2')
149 files changed, 4911 insertions, 936 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index fe40d9e488c9..46d9071f0938 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -4,7 +4,8 @@ # Common support obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \ - common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o + common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \ + omap_device.o # INTCPS IP block support - XXX should be moved to drivers/ obj-$(CONFIG_ARCH_OMAP2) += irq.o diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index d0c54c573d34..af11dcdb7e2c 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -18,7 +18,7 @@ #include <linux/err.h> #include <linux/davinci_emac.h> #include <asm/system.h> -#include <plat/omap_device.h> +#include "omap_device.h" #include "am35xx.h" #include "control.h" #include "am35xx-emac.h" diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 95b384d54f8a..49e49d0b7cf5 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -34,7 +34,7 @@ #include <asm/mach/map.h> #include "common.h" -#include <plat/gpmc.h> +#include "gpmc.h" #include <plat/usb.h> #include "gpmc-smc91x.h" diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 96cd3693e1ae..d2a419fcfce3 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -32,13 +32,14 @@ #include <plat/usb.h> #include "common.h" -#include <plat/dma.h> -#include <plat/gpmc.h> +#include <plat-omap/dma-omap.h> #include <video/omapdss.h> #include <video/omap-panel-tfp410.h> +#include "gpmc.h" #include "gpmc-smc91x.h" +#include "soc.h" #include "board-flash.h" #include "mux.h" #include "sdram-qimonda-hyb18m512160af-6.h" diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c index fc224ad86747..f1df60102a65 100644 --- a/arch/arm/mach-omap2/board-3630sdp.c +++ b/arch/arm/mach-omap2/board-3630sdp.c @@ -20,7 +20,7 @@ #include "gpmc-smc91x.h" #include <plat/usb.h> -#include <mach/board-zoom.h> +#include "board-zoom.h" #include "board-flash.h" #include "mux.h" diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 3669c120c7e8..2ab267ec3b75 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -35,7 +35,6 @@ #include "common.h" #include <plat/usb.h> -#include <plat/mmc.h> #include "omap4-keypad.h" #include <video/omapdss.h> #include <video/omap-panel-nokia-dsi.h> @@ -45,6 +44,7 @@ #include "soc.h" #include "mux.h" +#include "mmc.h" #include "hsmmc.h" #include "control.h" #include "common-board-devices.h" diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index cea3abace815..64cf1bde0f3b 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -28,14 +28,14 @@ #include <linux/clk.h> #include <linux/smc91x.h> #include <linux/gpio.h> +#include <linux/platform_data/leds-omap.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/flash.h> -#include <plat/led.h> #include "common.h" -#include <plat/gpmc.h> +#include "gpmc.h" #include <video/omapdss.h> #include <video/omap-panel-generic-dpi.h> diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 376d26eb601c..73e2ba9b343b 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -40,7 +40,7 @@ #include "common.h" #include <linux/platform_data/mtd-nand-omap2.h> -#include <plat/gpmc.h> +#include "gpmc.h" #include <plat/usb.h> #include <video/omapdss.h> #include <video/omap-panel-generic-dpi.h> @@ -53,6 +53,7 @@ #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" #include "common-board-devices.h" +#include "gpmc-nand.h" #define CM_T35_GPIO_PENDOWN 57 #define SB_T35_USB_HUB_RESET_GPIO 167 @@ -181,7 +182,7 @@ static struct omap_nand_platform_data cm_t35_nand_data = { static void __init cm_t35_init_nand(void) { - if (gpmc_nand_init(&cm_t35_nand_data) < 0) + if (gpmc_nand_init(&cm_t35_nand_data, NULL) < 0) pr_err("CM-T35: Unable to register NAND device\n"); } #else diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c index 59c0a45f75b0..b5495e415024 100644 --- a/arch/arm/mach-omap2/board-cm-t3517.c +++ b/arch/arm/mach-omap2/board-cm-t3517.c @@ -41,7 +41,7 @@ #include "common.h" #include <plat/usb.h> #include <linux/platform_data/mtd-nand-omap2.h> -#include <plat/gpmc.h> +#include "gpmc.h" #include "am35xx.h" @@ -49,6 +49,7 @@ #include "control.h" #include "common-board-devices.h" #include "am35xx-emac.h" +#include "gpmc-nand.h" #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) static struct gpio_led cm_t3517_leds[] = { @@ -240,7 +241,7 @@ static struct omap_nand_platform_data cm_t3517_nand_data = { static void __init cm_t3517_init_nand(void) { - if (gpmc_nand_init(&cm_t3517_nand_data) < 0) + if (gpmc_nand_init(&cm_t3517_nand_data, NULL) < 0) pr_err("CM-T3517: NAND initialization failed\n"); } #else diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 1fd161e934c7..3eedb8fd0370 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -39,7 +39,7 @@ #include <asm/mach/flash.h> #include "common.h" -#include <plat/gpmc.h> +#include "gpmc.h" #include <linux/platform_data/mtd-nand-omap2.h> #include <plat/usb.h> #include <video/omapdss.h> @@ -55,8 +55,11 @@ #include "sdram-micron-mt46h32m32lf-6.h" #include "mux.h" #include "hsmmc.h" +#include "board-flash.h" #include "common-board-devices.h" +#define NAND_CS 0 + #define OMAP_DM9000_GPIO_IRQ 25 #define OMAP3_DEVKIT_TS_GPIO 27 @@ -621,8 +624,9 @@ static void __init devkit8000_init(void) usb_musb_init(NULL); usbhs_init(&usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, - ARRAY_SIZE(devkit8000_nand_partitions)); + board_nand_init(devkit8000_nand_partitions, + ARRAY_SIZE(devkit8000_nand_partitions), NAND_CS, + NAND_BUSWIDTH_16, NULL); omap_twl4030_audio_init("omap3beagle"); /* Ensure SDRC pins are mux'd for self-refresh */ diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index e642acf9cad0..c33adea0247c 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -17,14 +17,14 @@ #include <linux/mtd/physmap.h> #include <linux/io.h> -#include <plat/cpu.h> -#include <plat/gpmc.h> #include <linux/platform_data/mtd-nand-omap2.h> #include <linux/platform_data/mtd-onenand-omap2.h> -#include <plat/tc.h> +#include "soc.h" #include "common.h" #include "board-flash.h" +#include "gpmc-onenand.h" +#include "gpmc-nand.h" #define REG_FPGA_REV 0x10 #define REG_FPGA_DIP_SWITCH_INPUT2 0x60 @@ -104,36 +104,35 @@ __init board_onenand_init(struct mtd_partition *onenand_parts, defined(CONFIG_MTD_NAND_OMAP2_MODULE) /* Note that all values in this struct are in nanoseconds */ -static struct gpmc_timings nand_timings = { +struct gpmc_timings nand_default_timings[1] = { + { + .sync_clk = 0, - .sync_clk = 0, + .cs_on = 0, + .cs_rd_off = 36, + .cs_wr_off = 36, - .cs_on = 0, - .cs_rd_off = 36, - .cs_wr_off = 36, + .adv_on = 6, + .adv_rd_off = 24, + .adv_wr_off = 36, - .adv_on = 6, - .adv_rd_off = 24, - .adv_wr_off = 36, + .we_off = 30, + .oe_off = 48, - .we_off = 30, - .oe_off = 48, + .access = 54, + .rd_cycle = 72, + .wr_cycle = 72, - .access = 54, - .rd_cycle = 72, - .wr_cycle = 72, - - .wr_access = 30, - .wr_data_mux_bus = 0, + .wr_access = 30, + .wr_data_mux_bus = 0, + }, }; -static struct omap_nand_platform_data board_nand_data = { - .gpmc_t = &nand_timings, -}; +static struct omap_nand_platform_data board_nand_data; void -__init board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) +__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, + int nand_type, struct gpmc_timings *gpmc_t) { board_nand_data.cs = cs; board_nand_data.parts = nand_parts; @@ -141,7 +140,7 @@ __init board_nand_init(struct mtd_partition *nand_parts, board_nand_data.devsize = nand_type; board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; - gpmc_nand_init(&board_nand_data); + gpmc_nand_init(&board_nand_data, gpmc_t); } #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ @@ -238,5 +237,6 @@ void __init board_flash_init(struct flash_partitions partition_info[], pr_err("NAND: Unable to find configuration in GPMC\n"); else board_nand_init(partition_info[2].parts, - partition_info[2].nr_parts, nandcs, nand_type); + partition_info[2].nr_parts, nandcs, + nand_type, nand_default_timings); } diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h index c44b70d52021..2fb5d41a9fae 100644 --- a/arch/arm/mach-omap2/board-flash.h +++ b/arch/arm/mach-omap2/board-flash.h @@ -12,7 +12,7 @@ */ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> -#include <plat/gpmc.h> +#include "gpmc.h" #define PDC_NOR 1 #define PDC_NAND 2 @@ -40,12 +40,14 @@ static inline void board_flash_init(struct flash_partitions part[], #if defined(CONFIG_MTD_NAND_OMAP2) || \ defined(CONFIG_MTD_NAND_OMAP2_MODULE) extern void board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type); + u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t); +extern struct gpmc_timings nand_default_timings[]; #else static inline void board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) + u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t) { } +#define nand_default_timings NULL #endif #if defined(CONFIG_MTD_ONENAND_OMAP2) || \ diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 8d04bf851af4..366ebd93ae24 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -32,8 +32,7 @@ #include <asm/mach/map.h> #include <plat/menelaus.h> -#include <plat/dma.h> -#include <plat/gpmc.h> +#include <plat-omap/dma-omap.h> #include "debug-devices.h" #include <video/omapdss.h> @@ -42,6 +41,7 @@ #include "common.h" #include "mux.h" #include "control.h" +#include "gpmc.h" #define H4_FLASH_CS 0 #define H4_SMC91X_CS 1 diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 48d5e41dfbfa..9a9a9b5f78b6 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -30,7 +30,7 @@ #include <asm/mach/arch.h> #include "common.h" -#include <plat/gpmc.h> +#include "gpmc.h" #include <plat/usb.h> #include <video/omapdss.h> @@ -43,6 +43,7 @@ #include "common-board-devices.h" #include "board-flash.h" #include "control.h" +#include "gpmc-onenand.h" #define IGEP2_SMSC911X_CS 5 #define IGEP2_SMSC911X_GPIO 176 @@ -175,7 +176,7 @@ static void __init igep_flash_init(void) pr_info("IGEP: initializing NAND memory device\n"); board_nand_init(igep_flash_partitions, ARRAY_SIZE(igep_flash_partitions), - 0, NAND_BUSWIDTH_16); + 0, NAND_BUSWIDTH_16, nand_default_timings); } else if (mux == IGEP_SYSBOOT_ONENAND) { pr_info("IGEP: initializing OneNAND memory device\n"); board_onenand_init(igep_flash_partitions, diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index ee8c3cfb95b3..35ee018d9289 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -35,8 +35,8 @@ #include <asm/mach/map.h> #include "common.h" -#include <plat/gpmc.h> -#include <mach/board-zoom.h> +#include "gpmc.h" +#include "board-zoom.h" #include <plat/usb.h> #include "gpmc-smsc911x.h" @@ -420,8 +420,8 @@ static void __init omap_ldp_init(void) omap_serial_init(); omap_sdrc_init(NULL, NULL); usb_musb_init(NULL); - board_nand_init(ldp_nand_partitions, - ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0); + board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions), + ZOOM_NAND_CS, 0, nand_default_timings); omap_hsmmc_init(mmc); ldp_display_init(); diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index d95f727ca39a..cea433b9b7b9 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -29,9 +29,10 @@ #include "common.h" #include <plat/menelaus.h> -#include <plat/mmc.h> +#include "mmc.h" #include "mux.h" +#include "gpmc-onenand.h" #define TUSB6010_ASYNC_CS 1 #define TUSB6010_SYNC_CS 4 diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 388c431c745a..a5497ce0a6c8 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -41,16 +41,20 @@ #include "common.h" #include <video/omapdss.h> #include <video/omap-panel-tfp410.h> -#include <plat/gpmc.h> +#include "gpmc.h" #include <linux/platform_data/mtd-nand-omap2.h> #include <plat/usb.h> -#include <plat/omap_device.h> +#include "omap_device.h" +#include "soc.h" #include "mux.h" #include "hsmmc.h" #include "pm.h" +#include "board-flash.h" #include "common-board-devices.h" +#define NAND_CS 0 + /* * OMAP3 Beagle revision * Run time detection of Beagle revision is done by reading GPIO. @@ -512,8 +516,9 @@ static void __init omap3_beagle_init(void) usb_musb_init(NULL); usbhs_init(&usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions, - ARRAY_SIZE(omap3beagle_nand_partitions)); + board_nand_init(omap3beagle_nand_partitions, + ARRAY_SIZE(omap3beagle_nand_partitions), NAND_CS, + NAND_BUSWIDTH_16, NULL); omap_twl4030_audio_init("omap3beagle"); /* Ensure msecure is mux'd to be able to set the RTC. */ diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index b9b776b6c954..8479779fd346 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -52,10 +52,14 @@ #include <video/omapdss.h> #include <video/omap-panel-tfp410.h> +#include "soc.h" #include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" #include "common-board-devices.h" +#include "board-flash.h" + +#define NAND_CS 0 #define OMAP3_EVM_TS_GPIO 175 #define OMAP3_EVM_EHCI_VBUS 22 @@ -731,8 +735,9 @@ static void __init omap3_evm_init(void) } usb_musb_init(&musb_board_data); usbhs_init(&usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, omap3evm_nand_partitions, - ARRAY_SIZE(omap3evm_nand_partitions)); + board_nand_init(omap3evm_nand_partitions, + ARRAY_SIZE(omap3evm_nand_partitions), NAND_CS, + NAND_BUSWIDTH_16, NULL); omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL); omap3evm_init_smsc911x(); diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c index 7bd8253b5d1d..6f58cad5bf74 100644 --- a/arch/arm/mach-omap2/board-omap3logic.c +++ b/arch/arm/mach-omap2/board-omap3logic.c @@ -34,9 +34,6 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include "gpmc-smsc911x.h" -#include <plat/gpmc.h> -#include <plat/sdrc.h> #include <plat/usb.h> #include "common.h" @@ -44,6 +41,8 @@ #include "hsmmc.h" #include "control.h" #include "common-board-devices.h" +#include "gpmc.h" +#include "gpmc-smsc911x.h" #define OMAP3LOGIC_SMSC911X_CS 1 diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 00a1f4ae6e44..f286b4b4bd5b 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -50,6 +50,7 @@ #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" #include "common-board-devices.h" +#include "gpmc-nand.h" #define PANDORA_WIFI_IRQ_GPIO 21 #define PANDORA_WIFI_NRESET_GPIO 23 @@ -602,7 +603,7 @@ static void __init omap3pandora_init(void) omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL); usbhs_init(&usbhs_bdata); usb_musb_init(NULL); - gpmc_nand_init(&pandora_nand_data); + gpmc_nand_init(&pandora_nand_data, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index 731235eb319e..3c83b9fbff45 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -40,7 +40,7 @@ #include <asm/mach/flash.h> #include "common.h" -#include <plat/gpmc.h> +#include "gpmc.h" #include <linux/platform_data/mtd-nand-omap2.h> #include <plat/usb.h> #include <video/omapdss.h> diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index 944ffc436577..cd282ae0856b 100644 --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c @@ -44,12 +44,13 @@ #include <asm/system_info.h> #include "common.h" -#include <plat/gpmc.h> +#include "gpmc.h" #include <linux/platform_data/mtd-nand-omap2.h> #include <plat/usb.h> #include "mux.h" #include "hsmmc.h" +#include "board-flash.h" #include "common-board-devices.h" #include <asm/setup.h> @@ -59,6 +60,8 @@ #define TB_BL_PWM_TIMER 9 #define TB_KILL_POWER_GPIO 168 +#define NAND_CS 0 + static unsigned long touchbook_revision; static struct mtd_partition omap3touchbook_nand_partitions[] = { @@ -365,8 +368,9 @@ static void __init omap3_touchbook_init(void) omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata); usb_musb_init(NULL); usbhs_init(&usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, omap3touchbook_nand_partitions, - ARRAY_SIZE(omap3touchbook_nand_partitions)); + board_nand_init(omap3touchbook_nand_partitions, + ARRAY_SIZE(omap3touchbook_nand_partitions), NAND_CS, + NAND_BUSWIDTH_16, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index bfcd397e233c..e9ce9fb9ffac 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -40,10 +40,10 @@ #include "common.h" #include <plat/usb.h> -#include <plat/mmc.h> #include <video/omap-panel-tfp410.h> #include "soc.h" +#include "mmc.h" #include "hsmmc.h" #include "control.h" #include "mux.h" diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index b700685762b5..3a9d1fa8bebd 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -49,14 +49,17 @@ #include <video/omapdss.h> #include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-tfp410.h> -#include <plat/gpmc.h> +#include "gpmc.h" #include <plat/usb.h> #include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" +#include "board-flash.h" #include "common-board-devices.h" +#define NAND_CS 0 + #define OVERO_GPIO_BT_XGATE 15 #define OVERO_GPIO_W2W_NRESET 16 #define OVERO_GPIO_PENDOWN 114 @@ -495,8 +498,8 @@ static void __init overo_init(void) omap_serial_init(); omap_sdrc_init(mt46h32m32lf6_sdrc_params, mt46h32m32lf6_sdrc_params); - omap_nand_flash_init(0, overo_nand_partitions, - ARRAY_SIZE(overo_nand_partitions)); + board_nand_init(overo_nand_partitions, + ARRAY_SIZE(overo_nand_partitions), NAND_CS, 0, NULL); usb_musb_init(NULL); usbhs_init(&usbhs_bdata); overo_spi_init(); diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c index 45997bfbcbd2..d42ecfe56096 100644 --- a/arch/arm/mach-omap2/board-rm680.c +++ b/arch/arm/mach-omap2/board-rm680.c @@ -22,17 +22,17 @@ #include <asm/mach/arch.h> #include <asm/mach-types.h> -#include <plat/i2c.h> -#include <plat/mmc.h> #include <plat/usb.h> -#include <plat/gpmc.h> +#include "gpmc.h" #include "common.h" #include <plat/serial.h> #include "mux.h" +#include "mmc.h" #include "hsmmc.h" #include "sdram-nokia.h" #include "common-board-devices.h" +#include "gpmc-onenand.h" static struct regulator_consumer_supply rm680_vemmc_consumers[] = { REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"), diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 020e03c95bfe..07005fe40a2a 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -31,9 +31,7 @@ #include <asm/system_info.h> #include "common.h" -#include <plat/dma.h> -#include <plat/gpmc.h> -#include <plat/omap-pm.h> +#include <plat-omap/dma-omap.h> #include "gpmc-smc91x.h" #include "board-rx51.h" @@ -52,8 +50,11 @@ #endif #include "mux.h" +#include "omap-pm.h" #include "hsmmc.h" #include "common-board-devices.h" +#include "gpmc.h" +#include "gpmc-onenand.h" #define SYSTEM_REV_B_USES_VAUX3 0x1699 #define SYSTEM_REV_S_USES_VAUX3 0x8 diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c index 7bbb05d9689b..63b33c63bd94 100644 --- a/arch/arm/mach-omap2/board-rx51.c +++ b/arch/arm/mach-omap2/board-rx51.c @@ -23,12 +23,12 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include "common.h" -#include <plat/dma.h> -#include <plat/gpmc.h> +#include <plat-omap/dma-omap.h> #include <plat/usb.h> +#include "common.h" #include "mux.h" +#include "gpmc.h" #include "pm.h" #include "sdram-nokia.h" diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c index afb2278a29f6..42e5f231a799 100644 --- a/arch/arm/mach-omap2/board-zoom-debugboard.c +++ b/arch/arm/mach-omap2/board-zoom-debugboard.c @@ -17,10 +17,10 @@ #include <linux/regulator/fixed.h> #include <linux/regulator/machine.h> -#include <plat/gpmc.h> +#include "gpmc.h" #include "gpmc-smsc911x.h" -#include <mach/board-zoom.h> +#include "board-zoom.h" #include "soc.h" #include "common.h" diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c index b940ab2259fb..1c7c834a5b5f 100644 --- a/arch/arm/mach-omap2/board-zoom-display.c +++ b/arch/arm/mach-omap2/board-zoom-display.c @@ -16,8 +16,9 @@ #include <linux/spi/spi.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <video/omapdss.h> -#include <mach/board-zoom.h> +#include "board-zoom.h" +#include "soc.h" #include "common.h" #define LCD_PANEL_RESET_GPIO_PROD 96 diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index c166fe1fdff9..74ac565ca9d0 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c @@ -28,7 +28,7 @@ #include "common.h" #include <plat/usb.h> -#include <mach/board-zoom.h> +#include "board-zoom.h" #include "mux.h" #include "hsmmc.h" diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c index 4994438e1f46..50e98795b09c 100644 --- a/arch/arm/mach-omap2/board-zoom.c +++ b/arch/arm/mach-omap2/board-zoom.c @@ -24,7 +24,7 @@ #include "common.h" #include <plat/usb.h> -#include <mach/board-zoom.h> +#include "board-zoom.h" #include "board-flash.h" #include "mux.h" @@ -113,8 +113,9 @@ static void __init omap_zoom_init(void) usbhs_init(&usbhs_bdata); } - board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions), - ZOOM_NAND_CS, NAND_BUSWIDTH_16); + board_nand_init(zoom_nand_partitions, + ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS, + NAND_BUSWIDTH_16, nand_default_timings); zoom_debugboard_init(); zoom_peripherals_init(); diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/board-zoom.h index 2e9486940ead..2e9486940ead 100644 --- a/arch/arm/mach-omap2/include/mach/board-zoom.h +++ b/arch/arm/mach-omap2/board-zoom.h diff --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c index c2d15212d64d..73a1414b89b0 100644 --- a/arch/arm/mach-omap2/clkt2xxx_apll.c +++ b/arch/arm/mach-omap2/clkt2xxx_apll.c @@ -21,7 +21,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> #include <plat/prcm.h> #include "clock.h" diff --git a/arch/arm/mach-omap2/clkt2xxx_dpll.c b/arch/arm/mach-omap2/clkt2xxx_dpll.c index 1502a7bc20bb..0890ba94a282 100644 --- a/arch/arm/mach-omap2/clkt2xxx_dpll.c +++ b/arch/arm/mach-omap2/clkt2xxx_dpll.c @@ -14,8 +14,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> - #include "clock.h" #include "cm2xxx_3xxx.h" #include "cm-regbits-24xx.h" diff --git a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c index 4ae439222085..3432f913f743 100644 --- a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c +++ b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c @@ -25,15 +25,14 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> -#include <plat/sram.h> -#include <plat/sdrc.h> +#include "../plat-omap/sram.h" #include "clock.h" #include "clock2xxx.h" #include "opp2xxx.h" #include "cm2xxx_3xxx.h" #include "cm-regbits-24xx.h" +#include "sdrc.h" /* #define DOWN_VARIABLE_DPLL 1 */ /* Experimental */ diff --git a/arch/arm/mach-omap2/clkt2xxx_osc.c b/arch/arm/mach-omap2/clkt2xxx_osc.c index c3460928b5e0..e1777371bb5e 100644 --- a/arch/arm/mach-omap2/clkt2xxx_osc.c +++ b/arch/arm/mach-omap2/clkt2xxx_osc.c @@ -23,8 +23,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> - #include "clock.h" #include "clock2xxx.h" #include "prm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/clkt2xxx_sys.c b/arch/arm/mach-omap2/clkt2xxx_sys.c index 8693cfdac49a..46683b3c2461 100644 --- a/arch/arm/mach-omap2/clkt2xxx_sys.c +++ b/arch/arm/mach-omap2/clkt2xxx_sys.c @@ -22,8 +22,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> - #include "clock.h" #include "clock2xxx.h" #include "prm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c index 3524f0e7b6d5..c66276b2bf0a 100644 --- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c +++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c @@ -33,9 +33,7 @@ #include <linux/cpufreq.h> #include <linux/slab.h> -#include <plat/clock.h> -#include <plat/sram.h> -#include <plat/sdrc.h> +#include "../plat-omap/sram.h" #include "soc.h" #include "clock.h" @@ -43,6 +41,7 @@ #include "opp2xxx.h" #include "cm2xxx_3xxx.h" #include "cm-regbits-24xx.h" +#include "sdrc.h" const struct prcm_config *curr_prcm_set; const struct prcm_config *rate_table; diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c index 7c6da2f731dc..5510d92abe6e 100644 --- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c +++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c @@ -21,9 +21,7 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> -#include <plat/sram.h> -#include <plat/sdrc.h> +#include "../plat-omap/sram.h" #include "clock.h" #include "clock3xxx.h" diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c index 3ff22114d702..53646facda45 100644 --- a/arch/arm/mach-omap2/clkt_clksel.c +++ b/arch/arm/mach-omap2/clkt_clksel.c @@ -45,8 +45,6 @@ #include <linux/io.h> #include <linux/bug.h> -#include <plat/clock.h> - #include "clock.h" /* Private functions */ diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c index 80411142f482..8463cc356245 100644 --- a/arch/arm/mach-omap2/clkt_dpll.c +++ b/arch/arm/mach-omap2/clkt_dpll.c @@ -21,8 +21,6 @@ #include <asm/div64.h> -#include <plat/clock.h> - #include "soc.h" #include "clock.h" #include "cm-regbits-24xx.h" diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c index 3d43fba2542f..7c8d41e49834 100644 --- a/arch/arm/mach-omap2/clkt_iclk.c +++ b/arch/arm/mach-omap2/clkt_iclk.c @@ -14,7 +14,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> #include <plat/prcm.h> #include "clock.h" diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 961ac8f7e13d..8b30759f8f9e 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -15,6 +15,7 @@ #undef DEBUG #include <linux/kernel.h> +#include <linux/export.h> #include <linux/list.h> #include <linux/errno.h> #include <linux/err.h> @@ -25,7 +26,6 @@ #include <asm/cpu.h> -#include <plat/clock.h> #include <plat/prcm.h> #include <trace/events/power.h> @@ -47,6 +47,10 @@ u16 cpu_mask; */ static bool clkdm_control = true; +static LIST_HEAD(clocks); +static DEFINE_MUTEX(clocks_mutex); +static DEFINE_SPINLOCK(clockfw_lock); + /* * OMAP2+ specific clock functions */ @@ -512,12 +516,510 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name, /* Common data */ -struct clk_functions omap2_clk_functions = { - .clk_enable = omap2_clk_enable, - .clk_disable = omap2_clk_disable, - .clk_round_rate = omap2_clk_round_rate, - .clk_set_rate = omap2_clk_set_rate, - .clk_set_parent = omap2_clk_set_parent, - .clk_disable_unused = omap2_clk_disable_unused, +int clk_enable(struct clk *clk) +{ + unsigned long flags; + int ret; + + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + + spin_lock_irqsave(&clockfw_lock, flags); + ret = omap2_clk_enable(clk); + spin_unlock_irqrestore(&clockfw_lock, flags); + + return ret; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + if (clk == NULL || IS_ERR(clk)) + return; + + spin_lock_irqsave(&clockfw_lock, flags); + if (clk->usecount == 0) { + pr_err("Trying disable clock %s with 0 usecount\n", + clk->name); + WARN_ON(1); + goto out; + } + + omap2_clk_disable(clk); + +out: + spin_unlock_irqrestore(&clockfw_lock, flags); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + unsigned long flags; + unsigned long ret; + + if (clk == NULL || IS_ERR(clk)) + return 0; + + spin_lock_irqsave(&clockfw_lock, flags); + ret = clk->rate; + spin_unlock_irqrestore(&clockfw_lock, flags); + + return ret; +} +EXPORT_SYMBOL(clk_get_rate); + +/* + * Optional clock functions defined in include/linux/clk.h + */ + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + long ret; + + if (clk == NULL || IS_ERR(clk)) + return 0; + + spin_lock_irqsave(&clockfw_lock, flags); + ret = omap2_clk_round_rate(clk, rate); + spin_unlock_irqrestore(&clockfw_lock, flags); + + return ret; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + int ret = -EINVAL; + + if (clk == NULL || IS_ERR(clk)) + return ret; + + spin_lock_irqsave(&clockfw_lock, flags); + ret = omap2_clk_set_rate(clk, rate); + if (ret == 0) + propagate_rate(clk); + spin_unlock_irqrestore(&clockfw_lock, flags); + + return ret; +} +EXPORT_SYMBOL(clk_set_rate); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + unsigned long flags; + int ret = -EINVAL; + + if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent)) + return ret; + + spin_lock_irqsave(&clockfw_lock, flags); + if (clk->usecount == 0) { + ret = omap2_clk_set_parent(clk, parent); + if (ret == 0) + propagate_rate(clk); + } else { + ret = -EBUSY; + } + spin_unlock_irqrestore(&clockfw_lock, flags); + + return ret; +} +EXPORT_SYMBOL(clk_set_parent); + +struct clk *clk_get_parent(struct clk *clk) +{ + return clk->parent; +} +EXPORT_SYMBOL(clk_get_parent); + +/* + * OMAP specific clock functions shared between omap1 and omap2 + */ + +int __initdata mpurate; + +/* + * By default we use the rate set by the bootloader. + * You can override this with mpurate= cmdline option. + */ +static int __init omap_clk_setup(char *str) +{ + get_option(&str, &mpurate); + + if (!mpurate) + return 1; + + if (mpurate < 1000) + mpurate *= 1000000; + + return 1; +} +__setup("mpurate=", omap_clk_setup); + +/* Used for clocks that always have same value as the parent clock */ +unsigned long followparent_recalc(struct clk *clk) +{ + return clk->parent->rate; +} + +/* + * Used for clocks that have the same value as the parent clock, + * divided by some factor + */ +unsigned long omap_fixed_divisor_recalc(struct clk *clk) +{ + WARN_ON(!clk->fixed_div); + + return clk->parent->rate / clk->fixed_div; +} + +void clk_reparent(struct clk *child, struct clk *parent) +{ + list_del_init(&child->sibling); + if (parent) + list_add(&child->sibling, &parent->children); + child->parent = parent; + + /* now do the debugfs renaming to reattach the child + to the proper parent */ +} + +/* Propagate rate to children */ +void propagate_rate(struct clk *tclk) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &tclk->children, sibling) { + if (clkp->recalc) + clkp->rate = clkp->recalc(clkp); + propagate_rate(clkp); + } +} + +static LIST_HEAD(root_clks); + +/** + * recalculate_root_clocks - recalculate and propagate all root clocks + * + * Recalculates all root clocks (clocks with no parent), which if the + * clock's .recalc is set correctly, should also propagate their rates. + * Called at init. + */ +void recalculate_root_clocks(void) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &root_clks, sibling) { + if (clkp->recalc) + clkp->rate = clkp->recalc(clkp); + propagate_rate(clkp); + } +} + +/** + * clk_preinit - initialize any fields in the struct clk before clk init + * @clk: struct clk * to initialize + * + * Initialize any struct clk fields needed before normal clk initialization + * can run. No return value. + */ +void clk_preinit(struct clk *clk) +{ + INIT_LIST_HEAD(&clk->children); +} + +int clk_register(struct clk *clk) +{ + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + + /* + * trap out already registered clocks + */ + if (clk->node.next || clk->node.prev) + return 0; + + mutex_lock(&clocks_mutex); + if (clk->parent) + list_add(&clk->sibling, &clk->parent->children); + else + list_add(&clk->sibling, &root_clks); + + list_add(&clk->node, &clocks); + if (clk->init) + clk->init(clk); + mutex_unlock(&clocks_mutex); + + return 0; +} +EXPORT_SYMBOL(clk_register); + +void clk_unregister(struct clk *clk) +{ + if (clk == NULL || IS_ERR(clk)) + return; + + mutex_lock(&clocks_mutex); + list_del(&clk->sibling); + list_del(&clk->node); + mutex_unlock(&clocks_mutex); +} +EXPORT_SYMBOL(clk_unregister); + +void clk_enable_init_clocks(void) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &clocks, node) + if (clkp->flags & ENABLE_ON_INIT) + clk_enable(clkp); +} + +/** + * omap_clk_get_by_name - locate OMAP struct clk by its name + * @name: name of the struct clk to locate + * + * Locate an OMAP struct clk by its name. Assumes that struct clk + * names are unique. Returns NULL if not found or a pointer to the + * struct clk if found. + */ +struct clk *omap_clk_get_by_name(const char *name) +{ + struct clk *c; + struct clk *ret = NULL; + + mutex_lock(&clocks_mutex); + + list_for_each_entry(c, &clocks, node) { + if (!strcmp(c->name, name)) { + ret = c; + break; + } + } + + mutex_unlock(&clocks_mutex); + + return ret; +} + +int omap_clk_enable_autoidle_all(void) +{ + struct clk *c; + unsigned long flags; + + spin_lock_irqsave(&clockfw_lock, flags); + + list_for_each_entry(c, &clocks, node) + if (c->ops->allow_idle) + c->ops->allow_idle(c); + + spin_unlock_irqrestore(&clockfw_lock, flags); + + return 0; +} + +int omap_clk_disable_autoidle_all(void) +{ + struct clk *c; + unsigned long flags; + + spin_lock_irqsave(&clockfw_lock, flags); + + list_for_each_entry(c, &clocks, node) + if (c->ops->deny_idle) + c->ops->deny_idle(c); + + spin_unlock_irqrestore(&clockfw_lock, flags); + + return 0; +} + +/* + * Low level helpers + */ +static int clkll_enable_null(struct clk *clk) +{ + return 0; +} + +static void clkll_disable_null(struct clk *clk) +{ +} + +const struct clkops clkops_null = { + .enable = clkll_enable_null, + .disable = clkll_disable_null, +}; + +/* + * Dummy clock + * + * Used for clock aliases that are needed on some OMAPs, but not others + */ +struct clk dummy_ck = { + .name = "dummy", + .ops = &clkops_null, +}; + +/* + * + */ + +#ifdef CONFIG_OMAP_RESET_CLOCKS +/* + * Disable any unused clocks left on by the bootloader + */ +static int __init clk_disable_unused(void) +{ + struct clk *ck; + unsigned long flags; + + pr_info("clock: disabling unused clocks to save power\n"); + + spin_lock_irqsave(&clockfw_lock, flags); + list_for_each_entry(ck, &clocks, node) { + if (ck->ops == &clkops_null) + continue; + + if (ck->usecount > 0 || !ck->enable_reg) + continue; + + omap2_clk_disable_unused(ck); + } + spin_unlock_irqrestore(&clockfw_lock, flags); + + return 0; +} +late_initcall(clk_disable_unused); +late_initcall(omap_clk_enable_autoidle_all); +#endif + +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) +/* + * debugfs support to trace clock tree hierarchy and attributes + */ + +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +static struct dentry *clk_debugfs_root; + +static int clk_dbg_show_summary(struct seq_file *s, void *unused) +{ + struct clk *c; + struct clk *pa; + + mutex_lock(&clocks_mutex); + seq_printf(s, "%-30s %-30s %-10s %s\n", + "clock-name", "parent-name", "rate", "use-count"); + + list_for_each_entry(c, &clocks, node) { + pa = c->parent; + seq_printf(s, "%-30s %-30s %-10lu %d\n", + c->name, pa ? pa->name : "none", c->rate, + c->usecount); + } + mutex_unlock(&clocks_mutex); + + return 0; +} + +static int clk_dbg_open(struct inode *inode, struct file *file) +{ + return single_open(file, clk_dbg_show_summary, inode->i_private); +} + +static const struct file_operations debug_clock_fops = { + .open = clk_dbg_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; +static int clk_debugfs_register_one(struct clk *c) +{ + int err; + struct dentry *d; + struct clk *pa = c->parent; + + d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root); + if (!d) + return -ENOMEM; + c->dent = d; + + d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount); + if (!d) { + err = -ENOMEM; + goto err_out; + } + d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); + if (!d) { + err = -ENOMEM; + goto err_out; + } + d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); + if (!d) { + err = -ENOMEM; + goto err_out; + } + return 0; + +err_out: + debugfs_remove_recursive(c->dent); + return err; +} + +static int clk_debugfs_register(struct clk *c) +{ + int err; + struct clk *pa = c->parent; + + if (pa && !pa->dent) { + err = clk_debugfs_register(pa); + if (err) + return err; + } + + if (!c->dent) { + err = clk_debugfs_register_one(c); + if (err) + return err; + } + return 0; +} + +static int __init clk_debugfs_init(void) +{ + struct clk *c; + struct dentry *d; + int err; + + d = debugfs_create_dir("clock", NULL); + if (!d) + return -ENOMEM; + clk_debugfs_root = d; + + list_for_each_entry(c, &clocks, node) { + err = clk_debugfs_register(c); + if (err) + goto err_out; + } + + d = debugfs_create_file("summary", S_IRUGO, + d, NULL, &debug_clock_fops); + if (!d) + return -ENOMEM; + + return 0; +err_out: + debugfs_remove_recursive(clk_debugfs_root); + return err; +} +late_initcall(clk_debugfs_init); + +#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */ + diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 35ec5f3d9a73..cfba1ffe5cc2 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -17,8 +17,323 @@ #define __ARCH_ARM_MACH_OMAP2_CLOCK_H #include <linux/kernel.h> +#include <linux/list.h> + +#include <linux/clkdev.h> + +struct omap_clk { + u16 cpu; + struct clk_lookup lk; +}; + +#define CLK(dev, con, ck, cp) \ + { \ + .cpu = cp, \ + .lk = { \ + .dev_id = dev, \ + .con_id = con, \ + .clk = ck, \ + }, \ + } + +/* Platform flags for the clkdev-OMAP integration code */ +#define CK_242X (1 << 0) +#define CK_243X (1 << 1) /* 243x, 253x */ +#define CK_3430ES1 (1 << 2) /* 34xxES1 only */ +#define CK_3430ES2PLUS (1 << 3) /* 34xxES2, ES3, non-Sitara 35xx only */ +#define CK_AM35XX (1 << 4) /* Sitara AM35xx */ +#define CK_36XX (1 << 5) /* 36xx/37xx-specific clocks */ +#define CK_443X (1 << 6) +#define CK_TI816X (1 << 7) +#define CK_446X (1 << 8) +#define CK_AM33XX (1 << 9) /* AM33xx specific clocks */ + + +#define CK_34XX (CK_3430ES1 | CK_3430ES2PLUS) +#define CK_3XXX (CK_34XX | CK_AM35XX | CK_36XX) + +struct module; +struct clk; +struct clockdomain; + +/* Temporary, needed during the common clock framework conversion */ +#define __clk_get_name(clk) (clk->name) +#define __clk_get_parent(clk) (clk->parent) +#define __clk_get_rate(clk) (clk->rate) + +/** + * struct clkops - some clock function pointers + * @enable: fn ptr that enables the current clock in hardware + * @disable: fn ptr that enables the current clock in hardware + * @find_idlest: function returning the IDLEST register for the clock's IP blk + * @find_companion: function returning the "companion" clk reg for the clock + * @allow_idle: fn ptr that enables autoidle for the current clock in hardware + * @deny_idle: fn ptr that disables autoidle for the current clock in hardware + * + * A "companion" clk is an accompanying clock to the one being queried + * that must be enabled for the IP module connected to the clock to + * become accessible by the hardware. Neither @find_idlest nor + * @find_companion should be needed; that information is IP + * block-specific; the hwmod code has been created to handle this, but + * until hwmod data is ready and drivers have been converted to use PM + * runtime calls in place of clk_enable()/clk_disable(), @find_idlest and + * @find_companion must, unfortunately, remain. + */ +struct clkops { + int (*enable)(struct clk *); + void (*disable)(struct clk *); + void (*find_idlest)(struct clk *, void __iomem **, + u8 *, u8 *); + void (*find_companion)(struct clk *, void __iomem **, + u8 *); + void (*allow_idle)(struct clk *); + void (*deny_idle)(struct clk *); +}; + +/* struct clksel_rate.flags possibilities */ +#define RATE_IN_242X (1 << 0) +#define RATE_IN_243X (1 << 1) +#define RATE_IN_3430ES1 (1 << 2) /* 3430ES1 rates only */ +#define RATE_IN_3430ES2PLUS (1 << 3) /* 3430 ES >= 2 rates only */ +#define RATE_IN_36XX (1 << 4) +#define RATE_IN_4430 (1 << 5) +#define RATE_IN_TI816X (1 << 6) +#define RATE_IN_4460 (1 << 7) +#define RATE_IN_AM33XX (1 << 8) +#define RATE_IN_TI814X (1 << 9) + +#define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X) +#define RATE_IN_34XX (RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS) +#define RATE_IN_3XXX (RATE_IN_34XX | RATE_IN_36XX) +#define RATE_IN_44XX (RATE_IN_4430 | RATE_IN_4460) + +/* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */ +#define RATE_IN_3430ES2PLUS_36XX (RATE_IN_3430ES2PLUS | RATE_IN_36XX) + + +/** + * struct clksel_rate - register bitfield values corresponding to clk divisors + * @val: register bitfield value (shifted to bit 0) + * @div: clock divisor corresponding to @val + * @flags: (see "struct clksel_rate.flags possibilities" above) + * + * @val should match the value of a read from struct clk.clksel_reg + * AND'ed with struct clk.clksel_mask, shifted right to bit 0. + * + * @div is the divisor that should be applied to the parent clock's rate + * to produce the current clock's rate. + */ +struct clksel_rate { + u32 val; + u8 div; + u16 flags; +}; + +/** + * struct clksel - available parent clocks, and a pointer to their divisors + * @parent: struct clk * to a possible parent clock + * @rates: available divisors for this parent clock + * + * A struct clksel is always associated with one or more struct clks + * and one or more struct clksel_rates. + */ +struct clksel { + struct clk *parent; + const struct clksel_rate *rates; +}; + +/** + * struct dpll_data - DPLL registers and integration data + * @mult_div1_reg: register containing the DPLL M and N bitfields + * @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg + * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg + * @clk_bypass: struct clk pointer to the clock's bypass clock input + * @clk_ref: struct clk pointer to the clock's reference clock input + * @control_reg: register containing the DPLL mode bitfield + * @enable_mask: mask of the DPLL mode bitfield in @control_reg + * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate() + * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate() + * @max_multiplier: maximum valid non-bypass multiplier value (actual) + * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate() + * @min_divider: minimum valid non-bypass divider value (actual) + * @max_divider: maximum valid non-bypass divider value (actual) + * @modes: possible values of @enable_mask + * @autoidle_reg: register containing the DPLL autoidle mode bitfield + * @idlest_reg: register containing the DPLL idle status bitfield + * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg + * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg + * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg + * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg + * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs + * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs + * @flags: DPLL type/features (see below) + * + * Possible values for @flags: + * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs) + * + * @freqsel_mask is only used on the OMAP34xx family and AM35xx. + * + * XXX Some DPLLs have multiple bypass inputs, so it's not technically + * correct to only have one @clk_bypass pointer. + * + * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m, + * @last_rounded_n) should be separated from the runtime-fixed fields + * and placed into a different structure, so that the runtime-fixed data + * can be placed into read-only space. + */ +struct dpll_data { + void __iomem *mult_div1_reg; + u32 mult_mask; + u32 div1_mask; + struct clk *clk_bypass; + struct clk *clk_ref; + void __iomem *control_reg; + u32 enable_mask; + unsigned long last_rounded_rate; + u16 last_rounded_m; + u16 max_multiplier; + u8 last_rounded_n; + u8 min_divider; + u16 max_divider; + u8 modes; + void __iomem *autoidle_reg; + void __iomem *idlest_reg; + u32 autoidle_mask; + u32 freqsel_mask; + u32 idlest_mask; + u32 dco_mask; + u32 sddiv_mask; + u8 auto_recal_bit; + u8 recal_en_bit; + u8 recal_st_bit; + u8 flags; +}; + +/* + * struct clk.flags possibilities + * + * XXX document the rest of the clock flags here + * + * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL + * bits share the same register. This flag allows the + * omap4_dpllmx*() code to determine which GATE_CTRL bit field + * should be used. This is a temporary solution - a better approach + * would be to associate clock type-specific data with the clock, + * similar to the struct dpll_data approach. + */ +#define ENABLE_REG_32BIT (1 << 0) /* Use 32-bit access */ +#define CLOCK_IDLE_CONTROL (1 << 1) +#define CLOCK_NO_IDLE_PARENT (1 << 2) +#define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */ +#define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */ +#define CLOCK_CLKOUTX2 (1 << 5) + +/** + * struct clk - OMAP struct clk + * @node: list_head connecting this clock into the full clock list + * @ops: struct clkops * for this clock + * @name: the name of the clock in the hardware (used in hwmod data and debug) + * @parent: pointer to this clock's parent struct clk + * @children: list_head connecting to the child clks' @sibling list_heads + * @sibling: list_head connecting this clk to its parent clk's @children + * @rate: current clock rate + * @enable_reg: register to write to enable the clock (see @enable_bit) + * @recalc: fn ptr that returns the clock's current rate + * @set_rate: fn ptr that can change the clock's current rate + * @round_rate: fn ptr that can round the clock's current rate + * @init: fn ptr to do clock-specific initialization + * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg) + * @usecount: number of users that have requested this clock to be enabled + * @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div + * @flags: see "struct clk.flags possibilities" above + * @clksel_reg: for clksel clks, register va containing src/divisor select + * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector + * @clksel: for clksel clks, pointer to struct clksel for this clock + * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock + * @clkdm_name: clockdomain name that this clock is contained in + * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime + * @rate_offset: bitshift for rate selection bitfield (OMAP1 only) + * @src_offset: bitshift for source selection bitfield (OMAP1 only) + * + * XXX @rate_offset, @src_offset should probably be removed and OMAP1 + * clock code converted to use clksel. + * + * XXX @usecount is poorly named. It should be "enable_count" or + * something similar. "users" in the description refers to kernel + * code (core code or drivers) that have called clk_enable() and not + * yet called clk_disable(); the usecount of parent clocks is also + * incremented by the clock code when clk_enable() is called on child + * clocks and decremented by the clock code when clk_disable() is + * called on child clocks. + * + * XXX @clkdm, @usecount, @children, @sibling should be marked for + * internal use only. + * + * @children and @sibling are used to optimize parent-to-child clock + * tree traversals. (child-to-parent traversals use @parent.) + * + * XXX The notion of the clock's current rate probably needs to be + * separated from the clock's target rate. + */ +struct clk { + struct list_head node; + const struct clkops *ops; + const char *name; + struct clk *parent; + struct list_head children; + struct list_head sibling; /* node for children */ + unsigned long rate; + void __iomem *enable_reg; + unsigned long (*recalc)(struct clk *); + int (*set_rate)(struct clk *, unsigned long); + long (*round_rate)(struct clk *, unsigned long); + void (*init)(struct clk *); + u8 enable_bit; + s8 usecount; + u8 fixed_div; + u8 flags; + void __iomem *clksel_reg; + u32 clksel_mask; + const struct clksel *clksel; + struct dpll_data *dpll_data; + const char *clkdm_name; + struct clockdomain *clkdm; +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) + struct dentry *dent; /* For visible tree hierarchy */ +#endif +}; + +struct clk_functions { + int (*clk_enable)(struct clk *clk); + void (*clk_disable)(struct clk *clk); + long (*clk_round_rate)(struct clk *clk, unsigned long rate); + int (*clk_set_rate)(struct clk *clk, unsigned long rate); + int (*clk_set_parent)(struct clk *clk, struct clk *parent); + void (*clk_allow_idle)(struct clk *clk); + void (*clk_deny_idle)(struct clk *clk); + void (*clk_disable_unused)(struct clk *clk); +}; + +extern int mpurate; + +extern int clk_init(struct clk_functions *custom_clocks); +extern void clk_preinit(struct clk *clk); +extern int clk_register(struct clk *clk); +extern void clk_reparent(struct clk *child, struct clk *parent); +extern void clk_unregister(struct clk *clk); +extern void propagate_rate(struct clk *clk); +extern void recalculate_root_clocks(void); +extern unsigned long followparent_recalc(struct clk *clk); +extern void clk_enable_init_clocks(void); +unsigned long omap_fixed_divisor_recalc(struct clk *clk); +extern struct clk *omap_clk_get_by_name(const char *name); +extern int omap_clk_enable_autoidle_all(void); +extern int omap_clk_disable_autoidle_all(void); + +extern const struct clkops clkops_null; + +extern struct clk dummy_ck; -#include <plat/clock.h> /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */ #define CORE_CLK_SRC_32K 0x0 diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index c3cde1a2b6de..ff47a6c2611d 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -18,8 +18,6 @@ #include <linux/clk.h> #include <linux/list.h> -#include <plat/clkdev_omap.h> - #include "soc.h" #include "iomap.h" #include "clock.h" @@ -1935,8 +1933,6 @@ int __init omap2420_clk_init(void) cpu_mask = RATE_IN_242X; rate_table = omap2420_rate_table; - clk_init(&omap2_clk_functions); - for (c = omap2420_clks; c < omap2420_clks + ARRAY_SIZE(omap2420_clks); c++) clk_preinit(c->lk.clk); diff --git a/arch/arm/mach-omap2/clock2430.c b/arch/arm/mach-omap2/clock2430.c index a8e326177466..850f83e8954f 100644 --- a/arch/arm/mach-omap2/clock2430.c +++ b/arch/arm/mach-omap2/clock2430.c @@ -21,8 +21,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> - #include "soc.h" #include "iomap.h" #include "clock.h" diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 22404fe435e7..cab8e9c52d6e 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -17,8 +17,6 @@ #include <linux/clk.h> #include <linux/list.h> -#include <plat/clkdev_omap.h> - #include "soc.h" #include "iomap.h" #include "clock.h" @@ -2034,8 +2032,6 @@ int __init omap2430_clk_init(void) cpu_mask = RATE_IN_243X; rate_table = omap2430_rate_table; - clk_init(&omap2_clk_functions); - for (c = omap2430_clks; c < omap2430_clks + ARRAY_SIZE(omap2430_clks); c++) clk_preinit(c->lk.clk); diff --git a/arch/arm/mach-omap2/clock2xxx.c b/arch/arm/mach-omap2/clock2xxx.c index e92be1fc1a00..5feee16fee0e 100644 --- a/arch/arm/mach-omap2/clock2xxx.c +++ b/arch/arm/mach-omap2/clock2xxx.c @@ -22,8 +22,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> - #include "soc.h" #include "clock.h" #include "clock2xxx.h" diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c index 114ab4b8e0e3..1cb79cc58089 100644 --- a/arch/arm/mach-omap2/clock33xx_data.c +++ b/arch/arm/mach-omap2/clock33xx_data.c @@ -17,9 +17,8 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/clk.h> -#include <plat/clkdev_omap.h> -#include "am33xx.h" +#include "soc.h" #include "iomap.h" #include "control.h" #include "clock.h" @@ -1085,8 +1084,6 @@ int __init am33xx_clk_init(void) cpu_clkflg = CK_AM33XX; } - clk_init(&omap2_clk_functions); - for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) clk_preinit(c->lk.clk); diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 1fc96b9ee330..baaaa4258708 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -21,8 +21,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> - #include "clock.h" #include "clock34xx.h" #include "cm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c index 2e97d08f0e56..80209050cd7a 100644 --- a/arch/arm/mach-omap2/clock3517.c +++ b/arch/arm/mach-omap2/clock3517.c @@ -21,8 +21,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> - #include "clock.h" #include "clock3517.h" #include "cm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/clock36xx.c b/arch/arm/mach-omap2/clock36xx.c index 0c5e25ed8879..0e1e9e4e2fa4 100644 --- a/arch/arm/mach-omap2/clock36xx.c +++ b/arch/arm/mach-omap2/clock36xx.c @@ -22,8 +22,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> - #include "clock.h" #include "clock36xx.h" diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c index 83bb01427d40..3e8aca2b1b61 100644 --- a/arch/arm/mach-omap2/clock3xxx.c +++ b/arch/arm/mach-omap2/clock3xxx.c @@ -21,8 +21,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> - #include "soc.h" #include "clock.h" #include "clock3xxx.h" diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 1f42c9d5ecf3..a02d158568e8 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -21,8 +21,6 @@ #include <linux/list.h> #include <linux/io.h> -#include <plat/clkdev_omap.h> - #include "soc.h" #include "iomap.h" #include "clock.h" @@ -3573,8 +3571,6 @@ int __init omap3xxx_clk_init(void) else dpll4_dd = dpll4_dd_34xx; - clk_init(&omap2_clk_functions); - for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); c++) clk_preinit(c->lk.clk); diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index d661d138f270..a66eeae3bc5d 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -28,8 +28,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clkdev_omap.h> - #include "soc.h" #include "iomap.h" #include "clock.h" @@ -3366,8 +3364,6 @@ int __init omap4xxx_clk_init(void) return 0; } - clk_init(&omap2_clk_functions); - /* * Must stay commented until all OMAP SoC drivers are * converted to runtime PM, or drivers may start crashing diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index cbb879139c51..467567ad526a 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -27,7 +27,8 @@ #include <linux/bitops.h> -#include <plat/clock.h> +#include "soc.h" +#include "clock.h" #include "clockdomain.h" /* clkdm_list contains all registered struct clockdomains */ diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 629576be7444..bc42446e23ab 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -18,9 +18,8 @@ #include <linux/spinlock.h> #include "powerdomain.h" -#include <plat/clock.h> -#include <plat/omap_hwmod.h> -#include <plat/cpu.h> +#include "clock.h" +#include "omap_hwmod.h" /* * Clockdomain flags diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c index 70294f54e35a..3e4e9209b2df 100644 --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c @@ -14,6 +14,8 @@ #include <linux/types.h> #include <plat/prcm.h> + +#include "soc.h" #include "prm.h" #include "prm2xxx_3xxx.h" #include "cm.h" diff --git a/arch/arm/mach-omap2/clockdomains2420_data.c b/arch/arm/mach-omap2/clockdomains2420_data.c index 5c741852fac0..7e76becf3a4a 100644 --- a/arch/arm/mach-omap2/clockdomains2420_data.c +++ b/arch/arm/mach-omap2/clockdomains2420_data.c @@ -35,6 +35,7 @@ #include <linux/kernel.h> #include <linux/io.h> +#include "soc.h" #include "clockdomain.h" #include "prm2xxx_3xxx.h" #include "cm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/clockdomains2430_data.c b/arch/arm/mach-omap2/clockdomains2430_data.c index f09617555e15..b923007e45d0 100644 --- a/arch/arm/mach-omap2/clockdomains2430_data.c +++ b/arch/arm/mach-omap2/clockdomains2430_data.c @@ -35,6 +35,7 @@ #include <linux/kernel.h> #include <linux/io.h> +#include "soc.h" #include "clockdomain.h" #include "prm2xxx_3xxx.h" #include "cm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c index 933a35cd124a..e6b91e552d3d 100644 --- a/arch/arm/mach-omap2/clockdomains3xxx_data.c +++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c @@ -33,6 +33,7 @@ #include <linux/kernel.h> #include <linux/io.h> +#include "soc.h" #include "clockdomain.h" #include "prm2xxx_3xxx.h" #include "cm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c index 13f56eafef03..b4938abf28cc 100644 --- a/arch/arm/mach-omap2/cm33xx.c +++ b/arch/arm/mach-omap2/cm33xx.c @@ -22,7 +22,7 @@ #include <linux/err.h> #include <linux/io.h> -#include <plat/common.h> +#include "../plat-omap/common.h" #include "cm.h" #include "cm33xx.h" diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c index 48daac2581b4..ad856092c06a 100644 --- a/arch/arm/mach-omap2/common-board-devices.c +++ b/arch/arm/mach-omap2/common-board-devices.c @@ -25,7 +25,6 @@ #include <linux/spi/ads7846.h> #include <linux/platform_data/spi-omap2-mcspi.h> -#include <linux/platform_data/mtd-nand-omap2.h> #include "common.h" #include "common-board-devices.h" @@ -96,48 +95,3 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, { } #endif - -#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) -static struct omap_nand_platform_data nand_data; - -void __init omap_nand_flash_init(int options, struct mtd_partition *parts, - int nr_parts) -{ - u8 cs = 0; - u8 nandcs = GPMC_CS_NUM + 1; - - /* find out the chip-select on which NAND exists */ - while (cs < GPMC_CS_NUM) { - u32 ret = 0; - ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); - - if ((ret & 0xC00) == 0x800) { - printk(KERN_INFO "Found NAND on CS%d\n", cs); - if (nandcs > GPMC_CS_NUM) - nandcs = cs; - } - cs++; - } - - if (nandcs > GPMC_CS_NUM) { - pr_info("NAND: Unable to find configuration in GPMC\n"); - return; - } - - if (nandcs < GPMC_CS_NUM) { - nand_data.cs = nandcs; - nand_data.parts = parts; - nand_data.nr_parts = nr_parts; - nand_data.devsize = options; - - printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (gpmc_nand_init(&nand_data) < 0) - printk(KERN_ERR "Unable to register NAND device\n"); - } -} -#else -void __init omap_nand_flash_init(int options, struct mtd_partition *parts, - int nr_parts) -{ -} -#endif diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h index a0b4a42836ab..72bb41b3fd25 100644 --- a/arch/arm/mach-omap2/common-board-devices.h +++ b/arch/arm/mach-omap2/common-board-devices.h @@ -10,6 +10,5 @@ struct ads7846_platform_data; void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, struct ads7846_platform_data *board_pdata); -void omap_nand_flash_init(int opts, struct mtd_partition *parts, int n_parts); #endif /* __OMAP_COMMON_BOARD_DEVICES__ */ diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c index 17950c6e130b..34fb5b95859b 100644 --- a/arch/arm/mach-omap2/common.c +++ b/arch/arm/mach-omap2/common.c @@ -16,14 +16,17 @@ #include <linux/init.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/platform_data/dsp-omap.h> -#include <plat/clock.h> +#include <plat/vram.h> #include "soc.h" #include "iomap.h" #include "common.h" +#include "clock.h" #include "sdrc.h" #include "control.h" +#include "omap-secure.h" /* Global address base setup code */ @@ -200,3 +203,20 @@ void __init omap5_map_io(void) omap5_map_common_io(); } #endif + +/* + * Stub function for OMAP2 so that common files + * continue to build when custom builds are used + */ +int __weak omap_secure_ram_reserve_memblock(void) +{ + return 0; +} + +void __init omap_reserve(void) +{ + omap_vram_reserve_sdram_memblock(); + omap_dsp_reserve_sdram_memblock(); + omap_secure_ram_reserve_memblock(); + omap_barrier_reserve_memblock(); +} diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index 7045e4d61ac3..d135d551d124 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -28,13 +28,17 @@ #include <linux/irq.h> #include <linux/delay.h> +#include <linux/i2c.h> #include <linux/i2c/twl.h> +#include <linux/i2c-omap.h> #include <asm/proc-fns.h> -#include <plat/cpu.h> #include <plat/serial.h> -#include <plat/common.h> + +#include "../plat-omap/common.h" + +#include "i2c.h" #define OMAP_INTC_START NR_IRQS @@ -338,6 +342,7 @@ extern void omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0, struct omap_sdrc_params *sdrc_cs1); struct omap2_hsmmc_info; extern int omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers); +extern void omap_reserve(void); #endif /* __ASSEMBLER__ */ #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */ diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index d1ff8399a222..bf2be5c5468d 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -1,7 +1,7 @@ /* * OMAP2/3 System Control Module register access * - * Copyright (C) 2007 Texas Instruments, Inc. + * Copyright (C) 2007, 2012 Texas Instruments, Inc. * Copyright (C) 2007 Nokia Corporation * * Written by Paul Walmsley @@ -15,8 +15,6 @@ #include <linux/kernel.h> #include <linux/io.h> -#include <plat/sdrc.h> - #include "soc.h" #include "iomap.h" #include "common.h" diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index c8c211731d26..86a5e13c9f59 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -23,10 +23,11 @@ #include <asm/mach-types.h> #include <asm/mach/map.h> +#include <plat-omap/dma-omap.h> + #include "iomap.h" -#include <plat/dma.h> -#include <plat/omap_hwmod.h> -#include <plat/omap_device.h> +#include "omap_hwmod.h" +#include "omap_device.h" #include "omap4-keypad.h" #include "soc.h" @@ -34,6 +35,7 @@ #include "mux.h" #include "control.h" #include "devices.h" +#include "dma.h" #define L3_MODULES_MAX_LEN 12 #define L3_MODULES 3 diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index 1011995f150a..89c57129357a 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -25,11 +25,12 @@ #include <linux/delay.h> #include <video/omapdss.h> -#include <plat/omap_hwmod.h> -#include <plat/omap_device.h> -#include <plat/omap-pm.h> +#include "omap_hwmod.h" +#include "omap_device.h" +#include "omap-pm.h" #include "common.h" +#include "soc.h" #include "iomap.h" #include "mux.h" #include "control.h" @@ -284,6 +285,35 @@ err: return ERR_PTR(r); } +static enum omapdss_version __init omap_display_get_version(void) +{ + if (cpu_is_omap24xx()) + return OMAPDSS_VER_OMAP24xx; + else if (cpu_is_omap3630()) + return OMAPDSS_VER_OMAP3630; + else if (cpu_is_omap34xx()) { + if (soc_is_am35xx()) { + return OMAPDSS_VER_AM35xx; + } else { + if (omap_rev() < OMAP3430_REV_ES3_0) + return OMAPDSS_VER_OMAP34xx_ES1; + else + return OMAPDSS_VER_OMAP34xx_ES3; + } + } else if (omap_rev() == OMAP4430_REV_ES1_0) + return OMAPDSS_VER_OMAP4430_ES1; + else if (omap_rev() == OMAP4430_REV_ES2_0 || + omap_rev() == OMAP4430_REV_ES2_1 || + omap_rev() == OMAP4430_REV_ES2_2) + return OMAPDSS_VER_OMAP4430_ES2; + else if (cpu_is_omap44xx()) + return OMAPDSS_VER_OMAP4; + else if (soc_is_omap54xx()) + return OMAPDSS_VER_OMAP5; + else + return OMAPDSS_VER_UNKNOWN; +} + int __init omap_display_init(struct omap_dss_board_info *board_data) { int r = 0; @@ -291,9 +321,18 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) int i, oh_count; const struct omap_dss_hwmod_data *curr_dss_hwmod; struct platform_device *dss_pdev; + enum omapdss_version ver; /* create omapdss device */ + ver = omap_display_get_version(); + + if (ver == OMAPDSS_VER_UNKNOWN) { + pr_err("DSS not supported on this SoC\n"); + return -ENODEV; + } + + board_data->version = ver; board_data->dsi_enable_pads = omap_dsi_enable_pads; board_data->dsi_disable_pads = omap_dsi_disable_pads; board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count; diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index ff75abe60af2..b1926cd70468 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -28,9 +28,11 @@ #include <linux/init.h> #include <linux/device.h> -#include <plat/omap_hwmod.h> -#include <plat/omap_device.h> -#include <plat/dma.h> +#include <plat-omap/dma-omap.h> + +#include "soc.h" +#include "omap_hwmod.h" +#include "omap_device.h" #define OMAP2_DMA_STRIDE 0x60 diff --git a/arch/arm/mach-omap2/dma.h b/arch/arm/mach-omap2/dma.h new file mode 100644 index 000000000000..eba80dbc5218 --- /dev/null +++ b/arch/arm/mach-omap2/dma.h @@ -0,0 +1,131 @@ +/* + * OMAP2PLUS DMA channel definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __OMAP2PLUS_DMA_CHANNEL_H +#define __OMAP2PLUS_DMA_CHANNEL_H + + +/* DMA channels for 24xx */ +#define OMAP24XX_DMA_NO_DEVICE 0 +#define OMAP24XX_DMA_XTI_DMA 1 /* S_DMA_0 */ +#define OMAP24XX_DMA_EXT_DMAREQ0 2 /* S_DMA_1 */ +#define OMAP24XX_DMA_EXT_DMAREQ1 3 /* S_DMA_2 */ +#define OMAP24XX_DMA_GPMC 4 /* S_DMA_3 */ +#define OMAP24XX_DMA_GFX 5 /* S_DMA_4 */ +#define OMAP24XX_DMA_DSS 6 /* S_DMA_5 */ +#define OMAP242X_DMA_VLYNQ_TX 7 /* S_DMA_6 */ +#define OMAP24XX_DMA_EXT_DMAREQ2 7 /* S_DMA_6 */ +#define OMAP24XX_DMA_CWT 8 /* S_DMA_7 */ +#define OMAP24XX_DMA_AES_TX 9 /* S_DMA_8 */ +#define OMAP24XX_DMA_AES_RX 10 /* S_DMA_9 */ +#define OMAP24XX_DMA_DES_TX 11 /* S_DMA_10 */ +#define OMAP24XX_DMA_DES_RX 12 /* S_DMA_11 */ +#define OMAP24XX_DMA_SHA1MD5_RX 13 /* S_DMA_12 */ +#define OMAP34XX_DMA_SHA2MD5_RX 13 /* S_DMA_12 */ +#define OMAP242X_DMA_EXT_DMAREQ2 14 /* S_DMA_13 */ +#define OMAP242X_DMA_EXT_DMAREQ3 15 /* S_DMA_14 */ +#define OMAP242X_DMA_EXT_DMAREQ4 16 /* S_DMA_15 */ +#define OMAP242X_DMA_EAC_AC_RD 17 /* S_DMA_16 */ +#define OMAP242X_DMA_EAC_AC_WR 18 /* S_DMA_17 */ +#define OMAP242X_DMA_EAC_MD_UL_RD 19 /* S_DMA_18 */ +#define OMAP242X_DMA_EAC_MD_UL_WR 20 /* S_DMA_19 */ +#define OMAP242X_DMA_EAC_MD_DL_RD 21 /* S_DMA_20 */ +#define OMAP242X_DMA_EAC_MD_DL_WR 22 /* S_DMA_21 */ +#define OMAP242X_DMA_EAC_BT_UL_RD 23 /* S_DMA_22 */ +#define OMAP242X_DMA_EAC_BT_UL_WR 24 /* S_DMA_23 */ +#define OMAP242X_DMA_EAC_BT_DL_RD 25 /* S_DMA_24 */ +#define OMAP242X_DMA_EAC_BT_DL_WR 26 /* S_DMA_25 */ +#define OMAP243X_DMA_EXT_DMAREQ3 14 /* S_DMA_13 */ +#define OMAP24XX_DMA_SPI3_TX0 15 /* S_DMA_14 */ +#define OMAP24XX_DMA_SPI3_RX0 16 /* S_DMA_15 */ +#define OMAP24XX_DMA_MCBSP3_TX 17 /* S_DMA_16 */ +#define OMAP24XX_DMA_MCBSP3_RX 18 /* S_DMA_17 */ +#define OMAP24XX_DMA_MCBSP4_TX 19 /* S_DMA_18 */ +#define OMAP24XX_DMA_MCBSP4_RX 20 /* S_DMA_19 */ +#define OMAP24XX_DMA_MCBSP5_TX 21 /* S_DMA_20 */ +#define OMAP24XX_DMA_MCBSP5_RX 22 /* S_DMA_21 */ +#define OMAP24XX_DMA_SPI3_TX1 23 /* S_DMA_22 */ +#define OMAP24XX_DMA_SPI3_RX1 24 /* S_DMA_23 */ +#define OMAP243X_DMA_EXT_DMAREQ4 25 /* S_DMA_24 */ +#define OMAP243X_DMA_EXT_DMAREQ5 26 /* S_DMA_25 */ +#define OMAP34XX_DMA_I2C3_TX 25 /* S_DMA_24 */ +#define OMAP34XX_DMA_I2C3_RX 26 /* S_DMA_25 */ +#define OMAP24XX_DMA_I2C1_TX 27 /* S_DMA_26 */ +#define OMAP24XX_DMA_I2C1_RX 28 /* S_DMA_27 */ +#define OMAP24XX_DMA_I2C2_TX 29 /* S_DMA_28 */ +#define OMAP24XX_DMA_I2C2_RX 30 /* S_DMA_29 */ +#define OMAP24XX_DMA_MCBSP1_TX 31 /* S_DMA_30 */ +#define OMAP24XX_DMA_MCBSP1_RX 32 /* S_DMA_31 */ +#define OMAP24XX_DMA_MCBSP2_TX 33 /* S_DMA_32 */ +#define OMAP24XX_DMA_MCBSP2_RX 34 /* S_DMA_33 */ +#define OMAP24XX_DMA_SPI1_TX0 35 /* S_DMA_34 */ +#define OMAP24XX_DMA_SPI1_RX0 36 /* S_DMA_35 */ +#define OMAP24XX_DMA_SPI1_TX1 37 /* S_DMA_36 */ +#define OMAP24XX_DMA_SPI1_RX1 38 /* S_DMA_37 */ +#define OMAP24XX_DMA_SPI1_TX2 39 /* S_DMA_38 */ +#define OMAP24XX_DMA_SPI1_RX2 40 /* S_DMA_39 */ +#define OMAP24XX_DMA_SPI1_TX3 41 /* S_DMA_40 */ +#define OMAP24XX_DMA_SPI1_RX3 42 /* S_DMA_41 */ +#define OMAP24XX_DMA_SPI2_TX0 43 /* S_DMA_42 */ +#define OMAP24XX_DMA_SPI2_RX0 44 /* S_DMA_43 */ +#define OMAP24XX_DMA_SPI2_TX1 45 /* S_DMA_44 */ +#define OMAP24XX_DMA_SPI2_RX1 46 /* S_DMA_45 */ +#define OMAP24XX_DMA_MMC2_TX 47 /* S_DMA_46 */ +#define OMAP24XX_DMA_MMC2_RX 48 /* S_DMA_47 */ +#define OMAP24XX_DMA_UART1_TX 49 /* S_DMA_48 */ +#define OMAP24XX_DMA_UART1_RX 50 /* S_DMA_49 */ +#define OMAP24XX_DMA_UART2_TX 51 /* S_DMA_50 */ +#define OMAP24XX_DMA_UART2_RX 52 /* S_DMA_51 */ +#define OMAP24XX_DMA_UART3_TX 53 /* S_DMA_52 */ +#define OMAP24XX_DMA_UART3_RX 54 /* S_DMA_53 */ +#define OMAP24XX_DMA_USB_W2FC_TX0 55 /* S_DMA_54 */ +#define OMAP24XX_DMA_USB_W2FC_RX0 56 /* S_DMA_55 */ +#define OMAP24XX_DMA_USB_W2FC_TX1 57 /* S_DMA_56 */ +#define OMAP24XX_DMA_USB_W2FC_RX1 58 /* S_DMA_57 */ +#define OMAP24XX_DMA_USB_W2FC_TX2 59 /* S_DMA_58 */ +#define OMAP24XX_DMA_USB_W2FC_RX2 60 /* S_DMA_59 */ +#define OMAP24XX_DMA_MMC1_TX 61 /* S_DMA_60 */ +#define OMAP24XX_DMA_MMC1_RX 62 /* S_DMA_61 */ +#define OMAP24XX_DMA_MS 63 /* S_DMA_62 */ +#define OMAP242X_DMA_EXT_DMAREQ5 64 /* S_DMA_63 */ +#define OMAP243X_DMA_EXT_DMAREQ6 64 /* S_DMA_63 */ +#define OMAP34XX_DMA_EXT_DMAREQ3 64 /* S_DMA_63 */ +#define OMAP34XX_DMA_AES2_TX 65 /* S_DMA_64 */ +#define OMAP34XX_DMA_AES2_RX 66 /* S_DMA_65 */ +#define OMAP34XX_DMA_DES2_TX 67 /* S_DMA_66 */ +#define OMAP34XX_DMA_DES2_RX 68 /* S_DMA_67 */ +#define OMAP34XX_DMA_SHA1MD5_RX 69 /* S_DMA_68 */ +#define OMAP34XX_DMA_SPI4_TX0 70 /* S_DMA_69 */ +#define OMAP34XX_DMA_SPI4_RX0 71 /* S_DMA_70 */ +#define OMAP34XX_DSS_DMA0 72 /* S_DMA_71 */ +#define OMAP34XX_DSS_DMA1 73 /* S_DMA_72 */ +#define OMAP34XX_DSS_DMA2 74 /* S_DMA_73 */ +#define OMAP34XX_DSS_DMA3 75 /* S_DMA_74 */ +#define OMAP34XX_DMA_MMC3_TX 77 /* S_DMA_76 */ +#define OMAP34XX_DMA_MMC3_RX 78 /* S_DMA_77 */ +#define OMAP34XX_DMA_USIM_TX 79 /* S_DMA_78 */ +#define OMAP34XX_DMA_USIM_RX 80 /* S_DMA_79 */ + +#define OMAP36XX_DMA_UART4_TX 81 /* S_DMA_80 */ +#define OMAP36XX_DMA_UART4_RX 82 /* S_DMA_81 */ + +/* Only for AM35xx */ +#define AM35XX_DMA_UART4_TX 54 +#define AM35XX_DMA_UART4_RX 55 + +#endif /* __OMAP2PLUS_DMA_CHANNEL_H */ diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index 814e1808e158..eacf51f2bc27 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -28,8 +28,6 @@ #include <linux/bitops.h> #include <linux/clkdev.h> -#include <plat/clock.h> - #include "soc.h" #include "clock.h" #include "cm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 09d0ccccb861..5854da168a9c 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -15,8 +15,6 @@ #include <linux/io.h> #include <linux/bitops.h> -#include <plat/clock.h> - #include "soc.h" #include "clock.h" #include "clock44xx.h" diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c index 72e0f01b715c..6282cc826613 100644 --- a/arch/arm/mach-omap2/drm.c +++ b/arch/arm/mach-omap2/drm.c @@ -24,8 +24,8 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> -#include <plat/omap_device.h> -#include <plat/omap_hwmod.h> +#include "omap_device.h" +#include "omap_hwmod.h" #if defined(CONFIG_DRM_OMAP) || (CONFIG_DRM_OMAP_MODULE) diff --git a/arch/arm/mach-omap2/dsp.c b/arch/arm/mach-omap2/dsp.c index 98388109f22a..b155500e84a8 100644 --- a/arch/arm/mach-omap2/dsp.c +++ b/arch/arm/mach-omap2/dsp.c @@ -27,7 +27,7 @@ #include "cm2xxx_3xxx.h" #include "prm2xxx_3xxx.h" #ifdef CONFIG_BRIDGE_DVFS -#include <plat/omap-pm.h> +#include "omap-pm.h" #endif #include <linux/platform_data/dsp-omap.h> diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index d1058f16fb40..399acabc3d0b 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -23,9 +23,9 @@ #include <linux/of.h> #include <linux/platform_data/gpio-omap.h> -#include <plat/omap_hwmod.h> -#include <plat/omap_device.h> -#include <plat/omap-pm.h> +#include "omap_hwmod.h" +#include "omap_device.h" +#include "omap-pm.h" #include "powerdomain.h" diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 4acf497faeb3..8607735b3ab3 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -17,9 +17,12 @@ #include <asm/mach/flash.h> -#include <plat/gpmc.h> - +#include "gpmc.h" #include "soc.h" +#include "gpmc-nand.h" + +/* minimum size for IO mapping */ +#define NAND_IO_SIZE 4 static struct resource gpmc_nand_resource[] = { { @@ -40,41 +43,36 @@ static struct platform_device gpmc_nand_device = { .resource = gpmc_nand_resource, }; -static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data) +static int omap2_nand_gpmc_retime( + struct omap_nand_platform_data *gpmc_nand_data, + struct gpmc_timings *gpmc_t) { struct gpmc_timings t; int err; - if (!gpmc_nand_data->gpmc_t) - return 0; - memset(&t, 0, sizeof(t)); - t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk; - t.cs_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_on); - t.adv_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->adv_on); + t.sync_clk = gpmc_t->sync_clk; + t.cs_on = gpmc_round_ns_to_ticks(gpmc_t->cs_on); + t.adv_on = gpmc_round_ns_to_ticks(gpmc_t->adv_on); /* Read */ - t.adv_rd_off = gpmc_round_ns_to_ticks( - gpmc_nand_data->gpmc_t->adv_rd_off); + t.adv_rd_off = gpmc_round_ns_to_ticks(gpmc_t->adv_rd_off); t.oe_on = t.adv_on; - t.access = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->access); - t.oe_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->oe_off); - t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_rd_off); - t.rd_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->rd_cycle); + t.access = gpmc_round_ns_to_ticks(gpmc_t->access); + t.oe_off = gpmc_round_ns_to_ticks(gpmc_t->oe_off); + t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_t->cs_rd_off); + t.rd_cycle = gpmc_round_ns_to_ticks(gpmc_t->rd_cycle); /* Write */ - t.adv_wr_off = gpmc_round_ns_to_ticks( - gpmc_nand_data->gpmc_t->adv_wr_off); + t.adv_wr_off = gpmc_round_ns_to_ticks(gpmc_t->adv_wr_off); t.we_on = t.oe_on; if (cpu_is_omap34xx()) { - t.wr_data_mux_bus = gpmc_round_ns_to_ticks( - gpmc_nand_data->gpmc_t->wr_data_mux_bus); - t.wr_access = gpmc_round_ns_to_ticks( - gpmc_nand_data->gpmc_t->wr_access); + t.wr_data_mux_bus = gpmc_round_ns_to_ticks(gpmc_t->wr_data_mux_bus); + t.wr_access = gpmc_round_ns_to_ticks(gpmc_t->wr_access); } - t.we_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->we_off); - t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off); - t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle); + t.we_off = gpmc_round_ns_to_ticks(gpmc_t->we_off); + t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_t->cs_wr_off); + t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_t->wr_cycle); /* Configure GPMC */ if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) @@ -91,7 +89,29 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data return 0; } -int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) +static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) +{ + /* support only OMAP3 class */ + if (!cpu_is_omap34xx()) { + pr_err("BCH ecc is not supported on this CPU\n"); + return 0; + } + + /* + * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1. + * Other chips may be added if confirmed to work. + */ + if ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) && + (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) { + pr_err("BCH 4-bit mode is not supported on this CPU\n"); + return 0; + } + + return 1; +} + +int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, + struct gpmc_timings *gpmc_t) { int err = 0; struct device *dev = &gpmc_nand_device.dev; @@ -112,11 +132,13 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE); gpmc_nand_resource[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); - /* Set timings in GPMC */ - err = omap2_nand_gpmc_retime(gpmc_nand_data); - if (err < 0) { - dev_err(dev, "Unable to set gpmc timings: %d\n", err); - return err; + + if (gpmc_t) { + err = omap2_nand_gpmc_retime(gpmc_nand_data, gpmc_t); + if (err < 0) { + dev_err(dev, "Unable to set gpmc timings: %d\n", err); + return err; + } } /* Enable RD PIN Monitoring Reg */ @@ -126,6 +148,9 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs); + if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) + return -EINVAL; + err = platform_device_register(&gpmc_nand_device); if (err < 0) { dev_err(dev, "Unable to register NAND device\n"); diff --git a/arch/arm/mach-omap2/gpmc-nand.h b/arch/arm/mach-omap2/gpmc-nand.h new file mode 100644 index 000000000000..d59e1281e851 --- /dev/null +++ b/arch/arm/mach-omap2/gpmc-nand.h @@ -0,0 +1,27 @@ +/* + * arch/arm/mach-omap2/gpmc-nand.h + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __OMAP2_GPMC_NAND_H +#define __OMAP2_GPMC_NAND_H + +#include "gpmc.h" +#include <linux/platform_data/mtd-nand-omap2.h> + +#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2) +extern int gpmc_nand_init(struct omap_nand_platform_data *d, + struct gpmc_timings *gpmc_t); +#else +static inline int gpmc_nand_init(struct omap_nand_platform_data *d, + struct gpmc_timings *gpmc_t) +{ + return 0; +} +#endif + +#endif diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 916716e1da3b..d102183ed9a5 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -16,15 +16,25 @@ #include <linux/mtd/onenand_regs.h> #include <linux/io.h> #include <linux/platform_data/mtd-onenand-omap2.h> +#include <linux/err.h> #include <asm/mach/flash.h> -#include <plat/gpmc.h> - +#include "gpmc.h" #include "soc.h" +#include "gpmc-onenand.h" #define ONENAND_IO_SIZE SZ_128K +#define ONENAND_FLAG_SYNCREAD (1 << 0) +#define ONENAND_FLAG_SYNCWRITE (1 << 1) +#define ONENAND_FLAG_HF (1 << 2) +#define ONENAND_FLAG_VHF (1 << 3) + +static unsigned onenand_flags; +static unsigned latency; +static int fclk_offset; + static struct omap_onenand_platform_data *gpmc_onenand_data; static struct resource gpmc_onenand_resource = { @@ -38,11 +48,9 @@ static struct platform_device gpmc_onenand_device = { .resource = &gpmc_onenand_resource, }; -static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) +static struct gpmc_timings omap2_onenand_calc_async_timings(void) { struct gpmc_timings t; - u32 reg; - int err; const int t_cer = 15; const int t_avdp = 12; @@ -55,11 +63,6 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) const int t_wpl = 40; const int t_wph = 30; - /* Ensure sync read and sync write are disabled */ - reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); - reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE; - writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); - memset(&t, 0, sizeof(t)); t.sync_clk = 0; t.cs_on = 0; @@ -86,25 +89,30 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); + return t; +} + +static int gpmc_set_async_mode(int cs, struct gpmc_timings *t) +{ /* Configure GPMC for asynchronous read */ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_DEVICESIZE_16 | GPMC_CONFIG1_MUXADDDATA); - err = gpmc_cs_set_timings(cs, &t); - if (err) - return err; + return gpmc_cs_set_timings(cs, t); +} + +static void omap2_onenand_set_async_mode(void __iomem *onenand_base) +{ + u32 reg; /* Ensure sync read and sync write are disabled */ reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE; writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); - - return 0; } -static void set_onenand_cfg(void __iomem *onenand_base, int latency, - int sync_read, int sync_write, int hf, int vhf) +static void set_onenand_cfg(void __iomem *onenand_base) { u32 reg; @@ -112,19 +120,19 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency, reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9)); reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) | ONENAND_SYS_CFG1_BL_16; - if (sync_read) + if (onenand_flags & ONENAND_FLAG_SYNCREAD) reg |= ONENAND_SYS_CFG1_SYNC_READ; else reg &= ~ONENAND_SYS_CFG1_SYNC_READ; - if (sync_write) + if (onenand_flags & ONENAND_FLAG_SYNCWRITE) reg |= ONENAND_SYS_CFG1_SYNC_WRITE; else reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE; - if (hf) + if (onenand_flags & ONENAND_FLAG_HF) reg |= ONENAND_SYS_CFG1_HF; else reg &= ~ONENAND_SYS_CFG1_HF; - if (vhf) + if (onenand_flags & ONENAND_FLAG_VHF) reg |= ONENAND_SYS_CFG1_VHF; else reg &= ~ONENAND_SYS_CFG1_VHF; @@ -132,21 +140,10 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency, } static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, - void __iomem *onenand_base, bool *clk_dep) + void __iomem *onenand_base) { u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID); - int freq = 0; - - if (cfg->get_freq) { - struct onenand_freq_info fi; - - fi.maf_id = readw(onenand_base + ONENAND_REG_MANUFACTURER_ID); - fi.dev_id = readw(onenand_base + ONENAND_REG_DEVICE_ID); - fi.ver_id = ver; - freq = cfg->get_freq(&fi, clk_dep); - if (freq) - return freq; - } + int freq; switch ((ver >> 4) & 0xf) { case 0: @@ -172,9 +169,9 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, return freq; } -static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, - void __iomem *onenand_base, - int *freq_ptr) +static struct gpmc_timings +omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, + int freq) { struct gpmc_timings t; const int t_cer = 15; @@ -184,29 +181,15 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, const int t_wpl = 40; const int t_wph = 30; int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; - int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; - int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0; - int err, ticks_cez; - int cs = cfg->cs, freq = *freq_ptr; u32 reg; - bool clk_dep = false; + int div, fclk_offset_ns, gpmc_clk_ns; + int ticks_cez; + int cs = cfg->cs; - if (cfg->flags & ONENAND_SYNC_READ) { - sync_read = 1; - } else if (cfg->flags & ONENAND_SYNC_READWRITE) { - sync_read = 1; - sync_write = 1; - } else - return omap2_onenand_set_async_mode(cs, onenand_base); - - if (!freq) { - /* Very first call freq is not known */ - err = omap2_onenand_set_async_mode(cs, onenand_base); - if (err) - return err; - freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep); - first_time = 1; - } + if (cfg->flags & ONENAND_SYNC_READ) + onenand_flags = ONENAND_FLAG_SYNCREAD; + else if (cfg->flags & ONENAND_SYNC_READWRITE) + onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE; switch (freq) { case 104: @@ -244,44 +227,31 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, t_ach = 9; t_aavdh = 7; t_rdyo = 15; - sync_write = 0; + onenand_flags &= ~ONENAND_FLAG_SYNCWRITE; break; } - div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period); + div = gpmc_calc_divider(min_gpmc_clk_period); gpmc_clk_ns = gpmc_ticks_to_ns(div); if (gpmc_clk_ns < 15) /* >66Mhz */ - hf = 1; + onenand_flags |= ONENAND_FLAG_HF; + else + onenand_flags &= ~ONENAND_FLAG_HF; if (gpmc_clk_ns < 12) /* >83Mhz */ - vhf = 1; - if (vhf) + onenand_flags |= ONENAND_FLAG_VHF; + else + onenand_flags &= ~ONENAND_FLAG_VHF; + if (onenand_flags & ONENAND_FLAG_VHF) latency = 8; - else if (hf) + else if (onenand_flags & ONENAND_FLAG_HF) latency = 6; else if (gpmc_clk_ns >= 25) /* 40 MHz*/ latency = 3; else latency = 4; - if (clk_dep) { - if (gpmc_clk_ns < 12) { /* >83Mhz */ - t_ces = 3; - t_avds = 4; - } else if (gpmc_clk_ns < 15) { /* >66Mhz */ - t_ces = 5; - t_avds = 4; - } else if (gpmc_clk_ns < 25) { /* >40Mhz */ - t_ces = 6; - t_avds = 5; - } else { - t_ces = 7; - t_avds = 7; - } - } - - if (first_time) - set_onenand_cfg(onenand_base, latency, - sync_read, sync_write, hf, vhf); + /* Set synchronous read timings */ + memset(&t, 0, sizeof(t)); if (div == 1) { reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); @@ -307,8 +277,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); } - /* Set synchronous read timings */ - memset(&t, 0, sizeof(t)); t.sync_clk = min_gpmc_clk_period; t.cs_on = 0; t.adv_on = 0; @@ -330,7 +298,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, ticks_cez); /* Write */ - if (sync_write) { + if (onenand_flags & ONENAND_FLAG_SYNCWRITE) { t.adv_wr_off = t.adv_rd_off; t.we_on = 0; t.we_off = t.cs_rd_off; @@ -355,6 +323,14 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, } } + return t; +} + +static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t) +{ + unsigned sync_read = onenand_flags & ONENAND_FLAG_SYNCREAD; + unsigned sync_write = onenand_flags & ONENAND_FLAG_SYNCWRITE; + /* Configure GPMC for synchronous read */ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_WRAPBURST_SUPP | @@ -371,11 +347,45 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, GPMC_CONFIG1_DEVICETYPE_NOR | GPMC_CONFIG1_MUXADDDATA); - err = gpmc_cs_set_timings(cs, &t); - if (err) - return err; + return gpmc_cs_set_timings(cs, t); +} + +static int omap2_onenand_setup_async(void __iomem *onenand_base) +{ + struct gpmc_timings t; + int ret; + + omap2_onenand_set_async_mode(onenand_base); - set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf); + t = omap2_onenand_calc_async_timings(); + + ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t); + if (IS_ERR_VALUE(ret)) + return ret; + + omap2_onenand_set_async_mode(onenand_base); + + return 0; +} + +static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr) +{ + int ret, freq = *freq_ptr; + struct gpmc_timings t; + + if (!freq) { + /* Very first call freq is not known */ + freq = omap2_onenand_get_freq(gpmc_onenand_data, onenand_base); + set_onenand_cfg(onenand_base); + } + + t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq); + + ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t); + if (IS_ERR_VALUE(ret)) + return ret; + + set_onenand_cfg(onenand_base); *freq_ptr = freq; @@ -385,15 +395,22 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr) { struct device *dev = &gpmc_onenand_device.dev; + unsigned l = ONENAND_SYNC_READ | ONENAND_SYNC_READWRITE; + int ret; - /* Set sync timings in GPMC */ - if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base, - freq_ptr) < 0) { - dev_err(dev, "Unable to set synchronous mode\n"); - return -EINVAL; + ret = omap2_onenand_setup_async(onenand_base); + if (ret) { + dev_err(dev, "unable to set to async mode\n"); + return ret; } - return 0; + if (!(gpmc_onenand_data->flags & l)) + return 0; + + ret = omap2_onenand_setup_sync(onenand_base, freq_ptr); + if (ret) + dev_err(dev, "unable to set to sync mode\n"); + return ret; } void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) @@ -411,6 +428,11 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) gpmc_onenand_data->flags |= ONENAND_SYNC_READ; } + if (cpu_is_omap34xx()) + gpmc_onenand_data->flags |= ONENAND_IN_OMAP34XX; + else + gpmc_onenand_data->flags &= ~ONENAND_IN_OMAP34XX; + err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE, (unsigned long *)&gpmc_onenand_resource.start); if (err < 0) { diff --git a/arch/arm/mach-omap2/gpmc-onenand.h b/arch/arm/mach-omap2/gpmc-onenand.h new file mode 100644 index 000000000000..216f23a8b45c --- /dev/null +++ b/arch/arm/mach-omap2/gpmc-onenand.h @@ -0,0 +1,24 @@ +/* + * arch/arm/mach-omap2/gpmc-onenand.h + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __OMAP2_GPMC_ONENAND_H +#define __OMAP2_GPMC_ONENAND_H + +#include <linux/platform_data/mtd-onenand-omap2.h> + +#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) +extern void gpmc_onenand_init(struct omap_onenand_platform_data *d); +#else +#define board_onenand_data NULL +static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d) +{ +} +#endif + +#endif diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c index 565475310374..6eed907d594c 100644 --- a/arch/arm/mach-omap2/gpmc-smc91x.c +++ b/arch/arm/mach-omap2/gpmc-smc91x.c @@ -17,7 +17,7 @@ #include <linux/io.h> #include <linux/smc91x.h> -#include <plat/gpmc.h> +#include "gpmc.h" #include "gpmc-smc91x.h" #include "soc.h" diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c index 249a0b440cd6..ef990118d32b 100644 --- a/arch/arm/mach-omap2/gpmc-smsc911x.c +++ b/arch/arm/mach-omap2/gpmc-smsc911x.c @@ -20,7 +20,7 @@ #include <linux/io.h> #include <linux/smsc911x.h> -#include <plat/gpmc.h> +#include "gpmc.h" #include "gpmc-smsc911x.h" static struct resource gpmc_smsc911x_resources[] = { diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 5ac5cf30406a..6af1a5d98e6f 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -26,16 +26,14 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> -#include <asm/mach-types.h> -#include <plat/gpmc.h> +#include <linux/platform_data/mtd-nand-omap2.h> -#include <plat/cpu.h> -#include <plat/gpmc.h> -#include <plat/sdrc.h> -#include <plat/omap_device.h> +#include <asm/mach-types.h> #include "soc.h" #include "common.h" +#include "omap_device.h" +#include "gpmc.h" #define DEVICE_NAME "omap-gpmc" @@ -59,6 +57,9 @@ #define GPMC_ECC_SIZE_CONFIG 0x1fc #define GPMC_ECC1_RESULT 0x200 #define GPMC_ECC_BCH_RESULT_0 0x240 /* not available on OMAP2 */ +#define GPMC_ECC_BCH_RESULT_1 0x244 /* not available on OMAP2 */ +#define GPMC_ECC_BCH_RESULT_2 0x248 /* not available on OMAP2 */ +#define GPMC_ECC_BCH_RESULT_3 0x24c /* not available on OMAP2 */ /* GPMC ECC control settings */ #define GPMC_ECC_CTRL_ECCCLEAR 0x100 @@ -75,6 +76,7 @@ #define GPMC_CS0_OFFSET 0x60 #define GPMC_CS_SIZE 0x30 +#define GPMC_BCH_SIZE 0x10 #define GPMC_MEM_START 0x00000000 #define GPMC_MEM_END 0x3FFFFFFF @@ -137,7 +139,6 @@ static struct resource gpmc_mem_root; static struct resource gpmc_cs_mem[GPMC_CS_NUM]; static DEFINE_SPINLOCK(gpmc_mem_lock); static unsigned int gpmc_cs_map; /* flag for cs which are initialized */ -static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */ static struct device *gpmc_dev; static int gpmc_irq; static resource_size_t phys_base, mem_size; @@ -158,22 +159,6 @@ static u32 gpmc_read_reg(int idx) return __raw_readl(gpmc_base + idx); } -static void gpmc_cs_write_byte(int cs, int idx, u8 val) -{ - void __iomem *reg_addr; - - reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; - __raw_writeb(val, reg_addr); -} - -static u8 gpmc_cs_read_byte(int cs, int idx) -{ - void __iomem *reg_addr; - - reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; - return __raw_readb(reg_addr); -} - void gpmc_cs_write_reg(int cs, int idx, u32 val) { void __iomem *reg_addr; @@ -288,7 +273,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, return -1 #endif -int gpmc_cs_calc_divider(int cs, unsigned int sync_clk) +int gpmc_calc_divider(unsigned int sync_clk) { int div; u32 l; @@ -308,7 +293,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) int div; u32 l; - div = gpmc_cs_calc_divider(cs, t->sync_clk); + div = gpmc_calc_divider(t->sync_clk); if (div < 0) return div; @@ -509,44 +494,6 @@ void gpmc_cs_free(int cs) EXPORT_SYMBOL(gpmc_cs_free); /** - * gpmc_read_status - read access request to get the different gpmc status - * @cmd: command type - * @return status - */ -int gpmc_read_status(int cmd) -{ - int status = -EINVAL; - u32 regval = 0; - - switch (cmd) { - case GPMC_GET_IRQ_STATUS: - status = gpmc_read_reg(GPMC_IRQSTATUS); - break; - - case GPMC_PREFETCH_FIFO_CNT: - regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); - status = GPMC_PREFETCH_STATUS_FIFO_CNT(regval); - break; - - case GPMC_PREFETCH_COUNT: - regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); - status = GPMC_PREFETCH_STATUS_COUNT(regval); - break; - - case GPMC_STATUS_BUFFER: - regval = gpmc_read_reg(GPMC_STATUS); - /* 1 : buffer is available to write */ - status = regval & GPMC_STATUS_BUFF_EMPTY; - break; - - default: - printk(KERN_ERR "gpmc_read_status: Not supported\n"); - } - return status; -} -EXPORT_SYMBOL(gpmc_read_status); - -/** * gpmc_cs_configure - write request to configure gpmc * @cs: chip select number * @cmd: command type @@ -614,121 +561,10 @@ int gpmc_cs_configure(int cs, int cmd, int wval) } EXPORT_SYMBOL(gpmc_cs_configure); -/** - * gpmc_nand_read - nand specific read access request - * @cs: chip select number - * @cmd: command type - */ -int gpmc_nand_read(int cs, int cmd) -{ - int rval = -EINVAL; - - switch (cmd) { - case GPMC_NAND_DATA: - rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA); - break; - - default: - printk(KERN_ERR "gpmc_read_nand_ctrl: Not supported\n"); - } - return rval; -} -EXPORT_SYMBOL(gpmc_nand_read); - -/** - * gpmc_nand_write - nand specific write request - * @cs: chip select number - * @cmd: command type - * @wval: value to write - */ -int gpmc_nand_write(int cs, int cmd, int wval) -{ - int err = 0; - - switch (cmd) { - case GPMC_NAND_COMMAND: - gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval); - break; - - case GPMC_NAND_ADDRESS: - gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval); - break; - - case GPMC_NAND_DATA: - gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval); - - default: - printk(KERN_ERR "gpmc_write_nand_ctrl: Not supported\n"); - err = -EINVAL; - } - return err; -} -EXPORT_SYMBOL(gpmc_nand_write); - - - -/** - * gpmc_prefetch_enable - configures and starts prefetch transfer - * @cs: cs (chip select) number - * @fifo_th: fifo threshold to be used for read/ write - * @dma_mode: dma mode enable (1) or disable (0) - * @u32_count: number of bytes to be transferred - * @is_write: prefetch read(0) or write post(1) mode - */ -int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode, - unsigned int u32_count, int is_write) -{ - - if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) { - pr_err("gpmc: fifo threshold is not supported\n"); - return -1; - } else if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { - /* Set the amount of bytes to be prefetched */ - gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count); - - /* Set dma/mpu mode, the prefetch read / post write and - * enable the engine. Set which cs is has requested for. - */ - gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) | - PREFETCH_FIFOTHRESHOLD(fifo_th) | - ENABLE_PREFETCH | - (dma_mode << DMA_MPU_MODE) | - (0x1 & is_write))); - - /* Start the prefetch engine */ - gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1); - } else { - return -EBUSY; - } - - return 0; -} -EXPORT_SYMBOL(gpmc_prefetch_enable); - -/** - * gpmc_prefetch_reset - disables and stops the prefetch engine - */ -int gpmc_prefetch_reset(int cs) -{ - u32 config1; - - /* check if the same module/cs is trying to reset */ - config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1); - if (((config1 >> CS_NUM_SHIFT) & 0x7) != cs) - return -EINVAL; - - /* Stop the PFPW engine */ - gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0); - - /* Reset/disable the PFPW engine */ - gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0); - - return 0; -} -EXPORT_SYMBOL(gpmc_prefetch_reset); - void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) { + int i; + reg->gpmc_status = gpmc_base + GPMC_STATUS; reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET + GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs; @@ -744,7 +580,17 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL; reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG; reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT; - reg->gpmc_bch_result0 = gpmc_base + GPMC_ECC_BCH_RESULT_0; + + for (i = 0; i < GPMC_BCH_NUM_REMAINDER; i++) { + reg->gpmc_bch_result0[i] = gpmc_base + GPMC_ECC_BCH_RESULT_0 + + GPMC_BCH_SIZE * i; + reg->gpmc_bch_result1[i] = gpmc_base + GPMC_ECC_BCH_RESULT_1 + + GPMC_BCH_SIZE * i; + reg->gpmc_bch_result2[i] = gpmc_base + GPMC_ECC_BCH_RESULT_2 + + GPMC_BCH_SIZE * i; + reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 + + GPMC_BCH_SIZE * i; + } } int gpmc_get_client_irq(unsigned irq_config) @@ -1079,267 +925,3 @@ void omap3_gpmc_restore_context(void) } } #endif /* CONFIG_ARCH_OMAP3 */ - -/** - * gpmc_enable_hwecc - enable hardware ecc functionality - * @cs: chip select number - * @mode: read/write mode - * @dev_width: device bus width(1 for x16, 0 for x8) - * @ecc_size: bytes for which ECC will be generated - */ -int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size) -{ - unsigned int val; - - /* check if ecc module is in used */ - if (gpmc_ecc_used != -EINVAL) - return -EINVAL; - - gpmc_ecc_used = cs; - - /* clear ecc and enable bits */ - gpmc_write_reg(GPMC_ECC_CONTROL, - GPMC_ECC_CTRL_ECCCLEAR | - GPMC_ECC_CTRL_ECCREG1); - - /* program ecc and result sizes */ - val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); - gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); - - switch (mode) { - case GPMC_ECC_READ: - case GPMC_ECC_WRITE: - gpmc_write_reg(GPMC_ECC_CONTROL, - GPMC_ECC_CTRL_ECCCLEAR | - GPMC_ECC_CTRL_ECCREG1); - break; - case GPMC_ECC_READSYN: - gpmc_write_reg(GPMC_ECC_CONTROL, - GPMC_ECC_CTRL_ECCCLEAR | - GPMC_ECC_CTRL_ECCDISABLE); - break; - default: - printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode); - break; - } - - /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ - val = (dev_width << 7) | (cs << 1) | (0x1); - gpmc_write_reg(GPMC_ECC_CONFIG, val); - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_enable_hwecc); - -/** - * gpmc_calculate_ecc - generate non-inverted ecc bytes - * @cs: chip select number - * @dat: data pointer over which ecc is computed - * @ecc_code: ecc code buffer - * - * Using non-inverted ECC is considered ugly since writing a blank - * page (padding) will clear the ECC bytes. This is not a problem as long - * no one is trying to write data on the seemingly unused page. Reading - * an erased page will produce an ECC mismatch between generated and read - * ECC bytes that has to be dealt with separately. - */ -int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) -{ - unsigned int val = 0x0; - - if (gpmc_ecc_used != cs) - return -EINVAL; - - /* read ecc result */ - val = gpmc_read_reg(GPMC_ECC1_RESULT); - *ecc_code++ = val; /* P128e, ..., P1e */ - *ecc_code++ = val >> 16; /* P128o, ..., P1o */ - /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ - *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); - - gpmc_ecc_used = -EINVAL; - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_calculate_ecc); - -#ifdef CONFIG_ARCH_OMAP3 - -/** - * gpmc_init_hwecc_bch - initialize hardware BCH ecc functionality - * @cs: chip select number - * @nsectors: how many 512-byte sectors to process - * @nerrors: how many errors to correct per sector (4 or 8) - * - * This function must be executed before any call to gpmc_enable_hwecc_bch. - */ -int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors) -{ - /* check if ecc module is in use */ - if (gpmc_ecc_used != -EINVAL) - return -EINVAL; - - /* support only OMAP3 class */ - if (!cpu_is_omap34xx()) { - printk(KERN_ERR "BCH ecc is not supported on this CPU\n"); - return -EINVAL; - } - - /* - * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1. - * Other chips may be added if confirmed to work. - */ - if ((nerrors == 4) && - (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) { - printk(KERN_ERR "BCH 4-bit mode is not supported on this CPU\n"); - return -EINVAL; - } - - /* sanity check */ - if (nsectors > 8) { - printk(KERN_ERR "BCH cannot process %d sectors (max is 8)\n", - nsectors); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_init_hwecc_bch); - -/** - * gpmc_enable_hwecc_bch - enable hardware BCH ecc functionality - * @cs: chip select number - * @mode: read/write mode - * @dev_width: device bus width(1 for x16, 0 for x8) - * @nsectors: how many 512-byte sectors to process - * @nerrors: how many errors to correct per sector (4 or 8) - */ -int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors, - int nerrors) -{ - unsigned int val; - - /* check if ecc module is in use */ - if (gpmc_ecc_used != -EINVAL) - return -EINVAL; - - gpmc_ecc_used = cs; - - /* clear ecc and enable bits */ - gpmc_write_reg(GPMC_ECC_CONTROL, 0x1); - - /* - * When using BCH, sector size is hardcoded to 512 bytes. - * Here we are using wrapping mode 6 both for reading and writing, with: - * size0 = 0 (no additional protected byte in spare area) - * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) - */ - gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, (32 << 22) | (0 << 12)); - - /* BCH configuration */ - val = ((1 << 16) | /* enable BCH */ - (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */ - (0x06 << 8) | /* wrap mode = 6 */ - (dev_width << 7) | /* bus width */ - (((nsectors-1) & 0x7) << 4) | /* number of sectors */ - (cs << 1) | /* ECC CS */ - (0x1)); /* enable ECC */ - - gpmc_write_reg(GPMC_ECC_CONFIG, val); - gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_enable_hwecc_bch); - -/** - * gpmc_calculate_ecc_bch4 - Generate 7 ecc bytes per sector of 512 data bytes - * @cs: chip select number - * @dat: The pointer to data on which ecc is computed - * @ecc: The ecc output buffer - */ -int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc) -{ - int i; - unsigned long nsectors, reg, val1, val2; - - if (gpmc_ecc_used != cs) - return -EINVAL; - - nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1; - - for (i = 0; i < nsectors; i++) { - - reg = GPMC_ECC_BCH_RESULT_0 + 16*i; - - /* Read hw-computed remainder */ - val1 = gpmc_read_reg(reg + 0); - val2 = gpmc_read_reg(reg + 4); - - /* - * Add constant polynomial to remainder, in order to get an ecc - * sequence of 0xFFs for a buffer filled with 0xFFs; and - * left-justify the resulting polynomial. - */ - *ecc++ = 0x28 ^ ((val2 >> 12) & 0xFF); - *ecc++ = 0x13 ^ ((val2 >> 4) & 0xFF); - *ecc++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF)); - *ecc++ = 0x39 ^ ((val1 >> 20) & 0xFF); - *ecc++ = 0x96 ^ ((val1 >> 12) & 0xFF); - *ecc++ = 0xac ^ ((val1 >> 4) & 0xFF); - *ecc++ = 0x7f ^ ((val1 & 0xF) << 4); - } - - gpmc_ecc_used = -EINVAL; - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch4); - -/** - * gpmc_calculate_ecc_bch8 - Generate 13 ecc bytes per block of 512 data bytes - * @cs: chip select number - * @dat: The pointer to data on which ecc is computed - * @ecc: The ecc output buffer - */ -int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc) -{ - int i; - unsigned long nsectors, reg, val1, val2, val3, val4; - - if (gpmc_ecc_used != cs) - return -EINVAL; - - nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1; - - for (i = 0; i < nsectors; i++) { - - reg = GPMC_ECC_BCH_RESULT_0 + 16*i; - - /* Read hw-computed remainder */ - val1 = gpmc_read_reg(reg + 0); - val2 = gpmc_read_reg(reg + 4); - val3 = gpmc_read_reg(reg + 8); - val4 = gpmc_read_reg(reg + 12); - - /* - * Add constant polynomial to remainder, in order to get an ecc - * sequence of 0xFFs for a buffer filled with 0xFFs. - */ - *ecc++ = 0xef ^ (val4 & 0xFF); - *ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF); - *ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF); - *ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF); - *ecc++ = 0xed ^ (val3 & 0xFF); - *ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF); - *ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF); - *ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF); - *ecc++ = 0x97 ^ (val2 & 0xFF); - *ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF); - *ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF); - *ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF); - *ecc++ = 0xb5 ^ (val1 & 0xFF); - } - - gpmc_ecc_used = -EINVAL; - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch8); - -#endif /* CONFIG_ARCH_OMAP3 */ diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h new file mode 100644 index 000000000000..79f4dfc2adb3 --- /dev/null +++ b/arch/arm/mach-omap2/gpmc.h @@ -0,0 +1,135 @@ +/* + * General-Purpose Memory Controller for OMAP2 + * + * Copyright (C) 2005-2006 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __OMAP2_GPMC_H +#define __OMAP2_GPMC_H + +#include <linux/platform_data/mtd-nand-omap2.h> + +/* Maximum Number of Chip Selects */ +#define GPMC_CS_NUM 8 + +#define GPMC_CS_CONFIG1 0x00 +#define GPMC_CS_CONFIG2 0x04 +#define GPMC_CS_CONFIG3 0x08 +#define GPMC_CS_CONFIG4 0x0c +#define GPMC_CS_CONFIG5 0x10 +#define GPMC_CS_CONFIG6 0x14 +#define GPMC_CS_CONFIG7 0x18 +#define GPMC_CS_NAND_COMMAND 0x1c +#define GPMC_CS_NAND_ADDRESS 0x20 +#define GPMC_CS_NAND_DATA 0x24 + +/* Control Commands */ +#define GPMC_CONFIG_RDY_BSY 0x00000001 +#define GPMC_CONFIG_DEV_SIZE 0x00000002 +#define GPMC_CONFIG_DEV_TYPE 0x00000003 +#define GPMC_SET_IRQ_STATUS 0x00000004 +#define GPMC_CONFIG_WP 0x00000005 + +#define GPMC_ENABLE_IRQ 0x0000000d + +/* ECC commands */ +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ + +#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) +#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) +#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29) +#define GPMC_CONFIG1_READTYPE_SYNC (1 << 29) +#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28) +#define GPMC_CONFIG1_WRITETYPE_ASYNC (0 << 27) +#define GPMC_CONFIG1_WRITETYPE_SYNC (1 << 27) +#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25) +#define GPMC_CONFIG1_PAGE_LEN(val) ((val & 3) << 23) +#define GPMC_CONFIG1_WAIT_READ_MON (1 << 22) +#define GPMC_CONFIG1_WAIT_WRITE_MON (1 << 21) +#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18) +#define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) +#define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) +#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) +#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) +#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) +#define GPMC_CONFIG1_MUXADDDATA (1 << 9) +#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) +#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) +#define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1)) +#define GPMC_CONFIG1_FCLK_DIV3 (GPMC_CONFIG1_FCLK_DIV(2)) +#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) +#define GPMC_CONFIG7_CSVALID (1 << 6) + +#define GPMC_DEVICETYPE_NOR 0 +#define GPMC_DEVICETYPE_NAND 2 +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 +#define WR_RD_PIN_MONITORING 0x00600000 +#define GPMC_IRQ_FIFOEVENTENABLE 0x01 +#define GPMC_IRQ_COUNT_EVENT 0x02 + + +/* + * Note that all values in this struct are in nanoseconds except sync_clk + * (which is in picoseconds), while the register values are in gpmc_fck cycles. + */ +struct gpmc_timings { + /* Minimum clock period for synchronous mode (in picoseconds) */ + u32 sync_clk; + + /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ + u16 cs_on; /* Assertion time */ + u16 cs_rd_off; /* Read deassertion time */ + u16 cs_wr_off; /* Write deassertion time */ + + /* ADV signal timings corresponding to GPMC_CONFIG3 */ + u16 adv_on; /* Assertion time */ + u16 adv_rd_off; /* Read deassertion time */ + u16 adv_wr_off; /* Write deassertion time */ + + /* WE signals timings corresponding to GPMC_CONFIG4 */ + u16 we_on; /* WE assertion time */ + u16 we_off; /* WE deassertion time */ + + /* OE signals timings corresponding to GPMC_CONFIG4 */ + u16 oe_on; /* OE assertion time */ + u16 oe_off; /* OE deassertion time */ + + /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ + u16 page_burst_access; /* Multiple access word delay */ + u16 access; /* Start-cycle to first data valid delay */ + u16 rd_cycle; /* Total read cycle time */ + u16 wr_cycle; /* Total write cycle time */ + + /* The following are only on OMAP3430 */ + u16 wr_access; /* WRACCESSTIME */ + u16 wr_data_mux_bus; /* WRDATAONADMUXBUS */ +}; + +extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); +extern int gpmc_get_client_irq(unsigned irq_config); + +extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); +extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps); +extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); +extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns); +extern unsigned long gpmc_get_fclk_period(void); + +extern void gpmc_cs_write_reg(int cs, int idx, u32 val); +extern u32 gpmc_cs_read_reg(int cs, int idx); +extern int gpmc_calc_divider(unsigned int sync_clk); +extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t); +extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base); +extern void gpmc_cs_free(int cs); +extern int gpmc_cs_set_reserved(int cs, int reserved); +extern int gpmc_cs_reserved(int cs); +extern void omap3_gpmc_save_context(void); +extern void omap3_gpmc_restore_context(void); +extern int gpmc_cs_configure(int cs, int cmd, int wval); + +#endif diff --git a/arch/arm/mach-omap2/hdq1w.c b/arch/arm/mach-omap2/hdq1w.c index e003f2bba30c..3da8900598c8 100644 --- a/arch/arm/mach-omap2/hdq1w.c +++ b/arch/arm/mach-omap2/hdq1w.c @@ -27,8 +27,8 @@ #include <linux/err.h> #include <linux/platform_device.h> -#include <plat/omap_hwmod.h> -#include <plat/omap_device.h> +#include "omap_hwmod.h" +#include "omap_device.h" #include "hdq1w.h" #include "common.h" diff --git a/arch/arm/mach-omap2/hdq1w.h b/arch/arm/mach-omap2/hdq1w.h index 0c1efc846d8d..c7e08d2a7a46 100644 --- a/arch/arm/mach-omap2/hdq1w.h +++ b/arch/arm/mach-omap2/hdq1w.h @@ -21,7 +21,7 @@ #ifndef ARCH_ARM_MACH_OMAP2_HDQ1W_H #define ARCH_ARM_MACH_OMAP2_HDQ1W_H -#include <plat/omap_hwmod.h> +#include "omap_hwmod.h" /* * XXX A future cleanup patch should modify diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 4d3a6324155f..e3406dce59be 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -17,11 +17,12 @@ #include <mach/hardware.h> #include <linux/platform_data/gpio-omap.h> -#include <plat/mmc.h> -#include <plat/omap-pm.h> -#include <plat/omap_device.h> +#include "soc.h" +#include "omap_device.h" +#include "omap-pm.h" #include "mux.h" +#include "mmc.h" #include "hsmmc.h" #include "control.h" diff --git a/arch/arm/mach-omap2/hwspinlock.c b/arch/arm/mach-omap2/hwspinlock.c index 8763c8520dc2..1df9b5feda16 100644 --- a/arch/arm/mach-omap2/hwspinlock.c +++ b/arch/arm/mach-omap2/hwspinlock.c @@ -21,8 +21,8 @@ #include <linux/err.h> #include <linux/hwspinlock.h> -#include <plat/omap_hwmod.h> -#include <plat/omap_device.h> +#include "omap_hwmod.h" +#include "omap_device.h" static struct hwspinlock_pdata omap_hwspinlock_pdata __initdata = { .base_id = 0, diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c index fc57e67b321f..ad55b943108f 100644 --- a/arch/arm/mach-omap2/i2c.c +++ b/arch/arm/mach-omap2/i2c.c @@ -19,11 +19,13 @@ * */ -#include <plat/i2c.h> +#include "soc.h" #include "common.h" -#include <plat/omap_hwmod.h> +#include "omap_hwmod.h" +#include "omap_device.h" #include "mux.h" +#include "i2c.h" /* In register I2C_CON, Bit 15 is the I2C enable bit */ #define I2C_EN BIT(15) @@ -33,7 +35,9 @@ /* Maximum microseconds to wait for OMAP module to softreset */ #define MAX_MODULE_SOFTRESET_WAIT 10000 -void __init omap2_i2c_mux_pins(int bus_id) +#define MAX_OMAP_I2C_HWMOD_NAME_LEN 16 + +static void __init omap2_i2c_mux_pins(int bus_id) { char mux_name[sizeof("i2c2_scl.i2c2_scl")]; @@ -104,3 +108,46 @@ int omap_i2c_reset(struct omap_hwmod *oh) return 0; } + +static const char name[] = "omap_i2c"; + +int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata, + int bus_id) +{ + int l; + struct omap_hwmod *oh; + struct platform_device *pdev; + char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN]; + struct omap_i2c_bus_platform_data *pdata; + struct omap_i2c_dev_attr *dev_attr; + + omap2_i2c_mux_pins(bus_id); + + l = snprintf(oh_name, MAX_OMAP_I2C_HWMOD_NAME_LEN, "i2c%d", bus_id); + WARN(l >= MAX_OMAP_I2C_HWMOD_NAME_LEN, + "String buffer overflow in I2C%d device setup\n", bus_id); + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err("Could not look up %s\n", oh_name); + return -EEXIST; + } + + pdata = i2c_pdata; + /* + * pass the hwmod class's CPU-specific knowledge of I2C IP revision in + * use, and functionality implementation flags, up to the OMAP I2C + * driver via platform data + */ + pdata->rev = oh->class->rev; + + dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr; + pdata->flags = dev_attr->flags; + + pdev = omap_device_build(name, bus_id, oh, pdata, + sizeof(struct omap_i2c_bus_platform_data), + NULL, 0, 0); + WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name); + + return PTR_RET(pdev); +} + diff --git a/arch/arm/mach-omap2/i2c.h b/arch/arm/mach-omap2/i2c.h new file mode 100644 index 000000000000..81dbb992a6bc --- /dev/null +++ b/arch/arm/mach-omap2/i2c.h @@ -0,0 +1,42 @@ +/* + * Helper module for board specific I2C bus registration + * + * Copyright (C) 2009 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "../plat-omap/i2c.h" + +#ifndef __MACH_OMAP2_I2C_H +#define __MACH_OMAP2_I2C_H + +/** + * i2c_dev_attr - OMAP I2C controller device attributes for omap_hwmod + * @fifo_depth: total controller FIFO size (in bytes) + * @flags: differences in hardware support capability + * + * @fifo_depth represents what exists on the hardware, not what is + * actually configured at runtime by the device driver. + */ +struct omap_i2c_dev_attr { + u8 fifo_depth; + u32 flags; +}; + +int omap_i2c_reset(struct omap_hwmod *oh); + +#endif /* __MACH_OMAP2_I2C_H */ diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 4234d28dc171..80d1cf17af8c 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -25,14 +25,12 @@ #include <asm/tlb.h> #include <asm/mach/map.h> -#include <plat/sram.h> -#include <plat/sdrc.h> #include <plat/serial.h> -#include <plat/omap-pm.h> -#include <plat/omap_hwmod.h> -#include <plat/multi.h> -#include <plat/dma.h> +#include <plat-omap/dma-omap.h> +#include "../plat-omap/sram.h" + +#include "omap_hwmod.h" #include "soc.h" #include "iomap.h" #include "voltage.h" @@ -43,6 +41,8 @@ #include "clock2xxx.h" #include "clock3xxx.h" #include "clock44xx.h" +#include "omap-pm.h" +#include "sdrc.h" /* * The machine specific code may provide the extra mapping besides the diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 37f8f948047b..a106c75c5338 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -19,11 +19,12 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/platform_data/asoc-ti-mcbsp.h> - -#include <plat/dma.h> -#include <plat/omap_device.h> #include <linux/pm_runtime.h> +#include <plat-omap/dma-omap.h> + +#include "omap_device.h" + /* * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle. * Sidetone needs non-gated ICLK and sidetone autoidle is broken. diff --git a/arch/arm/mach-omap2/mmc.h b/arch/arm/mach-omap2/mmc.h new file mode 100644 index 000000000000..0cd4b089da9c --- /dev/null +++ b/arch/arm/mach-omap2/mmc.h @@ -0,0 +1,23 @@ +#include <linux/mmc/host.h> +#include <linux/platform_data/mmc-omap.h> + +#define OMAP24XX_NR_MMC 2 +#define OMAP2420_MMC_SIZE OMAP1_MMC_SIZE +#define OMAP2_MMC1_BASE 0x4809c000 + +#define OMAP4_MMC_REG_OFFSET 0x100 + +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) +void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data); +#else +static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) +{ +} +#endif + +struct omap_hwmod; +int omap_msdi_reset(struct omap_hwmod *oh); + +/* called from board-specific card detection service routine */ +extern void omap_mmc_notify_cover_event(struct device *dev, int slot, + int is_closed); diff --git a/arch/arm/mach-omap2/msdi.c b/arch/arm/mach-omap2/msdi.c index 9e57b4aadb06..627e97e30743 100644 --- a/arch/arm/mach-omap2/msdi.c +++ b/arch/arm/mach-omap2/msdi.c @@ -25,13 +25,12 @@ #include <linux/err.h> #include <linux/platform_data/gpio-omap.h> -#include <plat/omap_hwmod.h> -#include <plat/omap_device.h> -#include <plat/mmc.h> - #include "common.h" #include "control.h" +#include "omap_hwmod.h" +#include "omap_device.h" #include "mux.h" +#include "mmc.h" /* * MSDI_CON_OFFSET: offset in bytes of the MSDI IP block's CON register diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 701e17cba468..26126343d6ac 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -36,8 +36,9 @@ #include <linux/interrupt.h> -#include <plat/omap_hwmod.h> +#include "omap_hwmod.h" +#include "soc.h" #include "control.h" #include "mux.h" #include "prm.h" diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index ff4e6a0e9c7c..3f5fd7e3549d 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -50,6 +50,7 @@ #include <asm/suspend.h> #include <asm/hardware/cache-l2x0.h> +#include "soc.h" #include "common.h" #include "omap44xx.h" #include "omap4-sar-layout.h" diff --git a/arch/arm/mach-omap2/omap-pm.h b/arch/arm/mach-omap2/omap-pm.h new file mode 100644 index 000000000000..67faa7b8fe92 --- /dev/null +++ b/arch/arm/mach-omap2/omap-pm.h @@ -0,0 +1,352 @@ +/* + * omap-pm.h - OMAP power management interface + * + * Copyright (C) 2008-2010 Texas Instruments, Inc. + * Copyright (C) 2008-2010 Nokia Corporation + * Paul Walmsley + * + * Interface developed by (in alphabetical order): Karthik Dasu, Jouni + * Högander, Tony Lindgren, Rajendra Nayak, Sakari Poussa, + * Veeramanikandan Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, + * Richard Woodruff + */ + +#ifndef ASM_ARM_ARCH_OMAP_OMAP_PM_H +#define ASM_ARM_ARCH_OMAP_OMAP_PM_H + +#include <linux/device.h> +#include <linux/cpufreq.h> +#include <linux/clk.h> +#include <linux/opp.h> + +/* + * agent_id values for use with omap_pm_set_min_bus_tput(): + * + * OCP_INITIATOR_AGENT is only valid for devices that can act as + * initiators -- it represents the device's L3 interconnect + * connection. OCP_TARGET_AGENT represents the device's L4 + * interconnect connection. + */ +#define OCP_TARGET_AGENT 1 +#define OCP_INITIATOR_AGENT 2 + +/** + * omap_pm_if_early_init - OMAP PM init code called before clock fw init + * @mpu_opp_table: array ptr to struct omap_opp for MPU + * @dsp_opp_table: array ptr to struct omap_opp for DSP + * @l3_opp_table : array ptr to struct omap_opp for CORE + * + * Initialize anything that must be configured before the clock + * framework starts. The "_if_" is to avoid name collisions with the + * PM idle-loop code. + */ +int __init omap_pm_if_early_init(void); + +/** + * omap_pm_if_init - OMAP PM init code called after clock fw init + * + * The main initialization code. OPP tables are passed in here. The + * "_if_" is to avoid name collisions with the PM idle-loop code. + */ +int __init omap_pm_if_init(void); + +/** + * omap_pm_if_exit - OMAP PM exit code + * + * Exit code; currently unused. The "_if_" is to avoid name + * collisions with the PM idle-loop code. + */ +void omap_pm_if_exit(void); + +/* + * Device-driver-originated constraints (via board-*.c files, platform_data) + */ + + +/** + * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency + * @dev: struct device * requesting the constraint + * @t: maximum MPU wakeup latency in microseconds + * + * Request that the maximum interrupt latency for the MPU to be no + * greater than @t microseconds. "Interrupt latency" in this case is + * defined as the elapsed time from the occurrence of a hardware or + * timer interrupt to the time when the device driver's interrupt + * service routine has been entered by the MPU. + * + * It is intended that underlying PM code will use this information to + * determine what power state to put the MPU powerdomain into, and + * possibly the CORE powerdomain as well, since interrupt handling + * code currently runs from SDRAM. Advanced PM or board*.c code may + * also configure interrupt controller priorities, OCP bus priorities, + * CPU speed(s), etc. + * + * This function will not affect device wakeup latency, e.g., time + * elapsed from when a device driver enables a hardware device with + * clk_enable(), to when the device is ready for register access or + * other use. To control this device wakeup latency, use + * omap_pm_set_max_dev_wakeup_lat() + * + * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the + * previous t value. To remove the latency target for the MPU, call + * with t = -1. + * + * XXX This constraint will be deprecated soon in favor of the more + * general omap_pm_set_max_dev_wakeup_lat() + * + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. + */ +int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); + + +/** + * omap_pm_set_min_bus_tput - set minimum bus throughput needed by device + * @dev: struct device * requesting the constraint + * @tbus_id: interconnect to operate on (OCP_{INITIATOR,TARGET}_AGENT) + * @r: minimum throughput (in KiB/s) + * + * Request that the minimum data throughput on the OCP interconnect + * attached to device @dev interconnect agent @tbus_id be no less + * than @r KiB/s. + * + * It is expected that the OMAP PM or bus code will use this + * information to set the interconnect clock to run at the lowest + * possible speed that satisfies all current system users. The PM or + * bus code will adjust the estimate based on its model of the bus, so + * device driver authors should attempt to specify an accurate + * quantity for their device use case, and let the PM or bus code + * overestimate the numbers as necessary to handle request/response + * latency, other competing users on the system, etc. On OMAP2/3, if + * a driver requests a minimum L4 interconnect speed constraint, the + * code will also need to add an minimum L3 interconnect speed + * constraint, + * + * Multiple calls to omap_pm_set_min_bus_tput() will replace the + * previous rate value for this device. To remove the interconnect + * throughput restriction for this device, call with r = 0. + * + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. + */ +int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r); + + +/** + * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency + * @req_dev: struct device * requesting the constraint, or NULL if none + * @dev: struct device * to set the constraint one + * @t: maximum device wakeup latency in microseconds + * + * Request that the maximum amount of time necessary for a device @dev + * to become accessible after its clocks are enabled should be no + * greater than @t microseconds. Specifically, this represents the + * time from when a device driver enables device clocks with + * clk_enable(), to when the register reads and writes on the device + * will succeed. This function should be called before clk_disable() + * is called, since the power state transition decision may be made + * during clk_disable(). + * + * It is intended that underlying PM code will use this information to + * determine what power state to put the powerdomain enclosing this + * device into. + * + * Multiple calls to omap_pm_set_max_dev_wakeup_lat() will replace the + * previous wakeup latency values for this device. To remove the + * wakeup latency restriction for this device, call with t = -1. + * + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. + */ +int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, + long t); + + +/** + * omap_pm_set_max_sdma_lat - set the maximum system DMA transfer start latency + * @dev: struct device * + * @t: maximum DMA transfer start latency in microseconds + * + * Request that the maximum system DMA transfer start latency for this + * device 'dev' should be no greater than 't' microseconds. "DMA + * transfer start latency" here is defined as the elapsed time from + * when a device (e.g., McBSP) requests that a system DMA transfer + * start or continue, to the time at which data starts to flow into + * that device from the system DMA controller. + * + * It is intended that underlying PM code will use this information to + * determine what power state to put the CORE powerdomain into. + * + * Since system DMA transfers may not involve the MPU, this function + * will not affect MPU wakeup latency. Use set_max_cpu_lat() to do + * so. Similarly, this function will not affect device wakeup latency + * -- use set_max_dev_wakeup_lat() to affect that. + * + * Multiple calls to set_max_sdma_lat() will replace the previous t + * value for this device. To remove the maximum DMA latency for this + * device, call with t = -1. + * + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. + */ +int omap_pm_set_max_sdma_lat(struct device *dev, long t); + + +/** + * omap_pm_set_min_clk_rate - set minimum clock rate requested by @dev + * @dev: struct device * requesting the constraint + * @clk: struct clk * to set the minimum rate constraint on + * @r: minimum rate in Hz + * + * Request that the minimum clock rate on the device @dev's clk @clk + * be no less than @r Hz. + * + * It is expected that the OMAP PM code will use this information to + * find an OPP or clock setting that will satisfy this clock rate + * constraint, along with any other applicable system constraints on + * the clock rate or corresponding voltage, etc. + * + * omap_pm_set_min_clk_rate() differs from the clock code's + * clk_set_rate() in that it considers other constraints before taking + * any hardware action, and may change a system OPP rather than just a + * clock rate. clk_set_rate() is intended to be a low-level + * interface. + * + * omap_pm_set_min_clk_rate() is easily open to abuse. A better API + * would be something like "omap_pm_set_min_dev_performance()"; + * however, there is no easily-generalizable concept of performance + * that applies to all devices. Only a device (and possibly the + * device subsystem) has both the subsystem-specific knowledge, and + * the hardware IP block-specific knowledge, to translate a constraint + * on "touchscreen sampling accuracy" or "number of pixels or polygons + * rendered per second" to a clock rate. This translation can be + * dependent on the hardware IP block's revision, or firmware version, + * and the driver is the only code on the system that has this + * information and can know how to translate that into a clock rate. + * + * The intended use-case for this function is for userspace or other + * kernel code to communicate a particular performance requirement to + * a subsystem; then for the subsystem to communicate that requirement + * to something that is meaningful to the device driver; then for the + * device driver to convert that requirement to a clock rate, and to + * then call omap_pm_set_min_clk_rate(). + * + * Users of this function (such as device drivers) should not simply + * call this function with some high clock rate to ensure "high + * performance." Rather, the device driver should take a performance + * constraint from its subsystem, such as "render at least X polygons + * per second," and use some formula or table to convert that into a + * clock rate constraint given the hardware type and hardware + * revision. Device drivers or subsystems should not assume that they + * know how to make a power/performance tradeoff - some device use + * cases may tolerate a lower-fidelity device function for lower power + * consumption; others may demand a higher-fidelity device function, + * no matter what the power consumption. + * + * Multiple calls to omap_pm_set_min_clk_rate() will replace the + * previous rate value for the device @dev. To remove the minimum clock + * rate constraint for the device, call with r = 0. + * + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. + */ +int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r); + +/* + * DSP Bridge-specific constraints + */ + +/** + * omap_pm_dsp_get_opp_table - get OPP->DSP clock frequency table + * + * Intended for use by DSPBridge. Returns an array of OPP->DSP clock + * frequency entries. The final item in the array should have .rate = + * .opp_id = 0. + */ +const struct omap_opp *omap_pm_dsp_get_opp_table(void); + +/** + * omap_pm_dsp_set_min_opp - receive desired OPP target ID from DSP Bridge + * @opp_id: target DSP OPP ID + * + * Set a minimum OPP ID for the DSP. This is intended to be called + * only from the DSP Bridge MPU-side driver. Unfortunately, the only + * information that code receives from the DSP/BIOS load estimator is the + * target OPP ID; hence, this interface. No return value. + */ +void omap_pm_dsp_set_min_opp(u8 opp_id); + +/** + * omap_pm_dsp_get_opp - report the current DSP OPP ID + * + * Report the current OPP for the DSP. Since on OMAP3, the DSP and + * MPU share a single voltage domain, the OPP ID returned back may + * represent a higher DSP speed than the OPP requested via + * omap_pm_dsp_set_min_opp(). + * + * Returns the current VDD1 OPP ID, or 0 upon error. + */ +u8 omap_pm_dsp_get_opp(void); + + +/* + * CPUFreq-originated constraint + * + * In the future, this should be handled by custom OPP clocktype + * functions. + */ + +/** + * omap_pm_cpu_get_freq_table - return a cpufreq_frequency_table array ptr + * + * Provide a frequency table usable by CPUFreq for the current chip/board. + * Returns a pointer to a struct cpufreq_frequency_table array or NULL + * upon error. + */ +struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void); + +/** + * omap_pm_cpu_set_freq - set the current minimum MPU frequency + * @f: MPU frequency in Hz + * + * Set the current minimum CPU frequency. The actual CPU frequency + * used could end up higher if the DSP requested a higher OPP. + * Intended to be called by plat-omap/cpu_omap.c:omap_target(). No + * return value. + */ +void omap_pm_cpu_set_freq(unsigned long f); + +/** + * omap_pm_cpu_get_freq - report the current CPU frequency + * + * Returns the current MPU frequency, or 0 upon error. + */ +unsigned long omap_pm_cpu_get_freq(void); + + +/* + * Device context loss tracking + */ + +/** + * omap_pm_get_dev_context_loss_count - return count of times dev has lost ctx + * @dev: struct device * + * + * This function returns the number of times that the device @dev has + * lost its internal context. This generally occurs on a powerdomain + * transition to OFF. Drivers use this as an optimization to avoid restoring + * context if the device hasn't lost it. To use, drivers should initially + * call this in their context save functions and store the result. Early in + * the driver's context restore function, the driver should call this function + * again, and compare the result to the stored counter. If they differ, the + * driver must restore device context. If the number of context losses + * exceeds the maximum positive integer, the function will wrap to 0 and + * continue counting. Returns the number of context losses for this device, + * or negative value upon error. + */ +int omap_pm_get_dev_context_loss_count(struct device *dev); + +void omap_pm_enable_off_mode(void); +void omap_pm_disable_off_mode(void); + +#endif diff --git a/arch/arm/mach-omap2/omap-secure.c b/arch/arm/mach-omap2/omap-secure.c index e089e4d1ae38..b970440cffca 100644 --- a/arch/arm/mach-omap2/omap-secure.c +++ b/arch/arm/mach-omap2/omap-secure.c @@ -18,7 +18,6 @@ #include <asm/cacheflush.h> #include <asm/memblock.h> -#include <plat/omap-secure.h> #include "omap-secure.h" static phys_addr_t omap_secure_memblock_base; diff --git a/arch/arm/mach-omap2/omap-secure.h b/arch/arm/mach-omap2/omap-secure.h index c90a43589abe..0e729170c46b 100644 --- a/arch/arm/mach-omap2/omap-secure.h +++ b/arch/arm/mach-omap2/omap-secure.h @@ -52,6 +52,13 @@ extern u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2, u32 arg3, u32 arg4); extern u32 omap_smc2(u32 id, u32 falg, u32 pargs); extern phys_addr_t omap_secure_ram_mempool_base(void); +extern int omap_secure_ram_reserve_memblock(void); +#ifdef CONFIG_OMAP4_ERRATA_I688 +extern int omap_barrier_reserve_memblock(void); +#else +static inline void omap_barrier_reserve_memblock(void) +{ } +#endif #endif /* __ASSEMBLER__ */ #endif /* OMAP_ARCH_OMAP_SECURE_H */ diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index e1f289748c5d..d25845c471da 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -25,16 +25,15 @@ #include <asm/mach/map.h> #include <asm/memblock.h> -#include <plat/sram.h> -#include <plat/omap-secure.h> -#include <plat/mmc.h> +#include "../plat-omap/sram.h" #include "omap-wakeupgen.h" - #include "soc.h" #include "common.h" +#include "mmc.h" #include "hsmmc.h" #include "omap4-sar-layout.h" +#include "omap-secure.h" #ifdef CONFIG_CACHE_L2X0 static void __iomem *l2cache_base; diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c new file mode 100644 index 000000000000..0ef934fec364 --- /dev/null +++ b/arch/arm/mach-omap2/omap_device.c @@ -0,0 +1,1277 @@ +/* + * omap_device implementation + * + * Copyright (C) 2009-2010 Nokia Corporation + * Paul Walmsley, Kevin Hilman + * + * Developed in collaboration with (alphabetical order): Benoit + * Cousson, Thara Gopinath, Tony Lindgren, Rajendra Nayak, Vikram + * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard + * Woodruff + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This code provides a consistent interface for OMAP device drivers + * to control power management and interconnect properties of their + * devices. + * + * In the medium- to long-term, this code should either be + * a) implemented via arch-specific pointers in platform_data + * or + * b) implemented as a proper omap_bus/omap_device in Linux, no more + * platform_data func pointers + * + * + * Guidelines for usage by driver authors: + * + * 1. These functions are intended to be used by device drivers via + * function pointers in struct platform_data. As an example, + * omap_device_enable() should be passed to the driver as + * + * struct foo_driver_platform_data { + * ... + * int (*device_enable)(struct platform_device *pdev); + * ... + * } + * + * Note that the generic "device_enable" name is used, rather than + * "omap_device_enable". This is so other architectures can pass in their + * own enable/disable functions here. + * + * This should be populated during device setup: + * + * ... + * pdata->device_enable = omap_device_enable; + * ... + * + * 2. Drivers should first check to ensure the function pointer is not null + * before calling it, as in: + * + * if (pdata->device_enable) + * pdata->device_enable(pdev); + * + * This allows other architectures that don't use similar device_enable()/ + * device_shutdown() functions to execute normally. + * + * ... + * + * Suggested usage by device drivers: + * + * During device initialization: + * device_enable() + * + * During device idle: + * (save remaining device context if necessary) + * device_idle(); + * + * During device resume: + * device_enable(); + * (restore context if necessary) + * + * During device shutdown: + * device_shutdown() + * (device must be reinitialized at this point to use it again) + * + */ +#undef DEBUG + +#include <linux/kernel.h> +#include <linux/export.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/pm_runtime.h> +#include <linux/of.h> +#include <linux/notifier.h> + +#include "omap_device.h" +#include "omap_hwmod.h" + +/* These parameters are passed to _omap_device_{de,}activate() */ +#define USE_WAKEUP_LAT 0 +#define IGNORE_WAKEUP_LAT 1 + +static int omap_early_device_register(struct platform_device *pdev); + +static struct omap_device_pm_latency omap_default_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + } +}; + +/* Private functions */ + +/** + * _omap_device_activate - increase device readiness + * @od: struct omap_device * + * @ignore_lat: increase to latency target (0) or full readiness (1)? + * + * Increase readiness of omap_device @od (thus decreasing device + * wakeup latency, but consuming more power). If @ignore_lat is + * IGNORE_WAKEUP_LAT, make the omap_device fully active. Otherwise, + * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup + * latency is greater than the requested maximum wakeup latency, step + * backwards in the omap_device_pm_latency table to ensure the + * device's maximum wakeup latency is less than or equal to the + * requested maximum wakeup latency. Returns 0. + */ +static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) +{ + struct timespec a, b, c; + + dev_dbg(&od->pdev->dev, "omap_device: activating\n"); + + while (od->pm_lat_level > 0) { + struct omap_device_pm_latency *odpl; + unsigned long long act_lat = 0; + + od->pm_lat_level--; + + odpl = od->pm_lats + od->pm_lat_level; + + if (!ignore_lat && + (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit)) + break; + + read_persistent_clock(&a); + + /* XXX check return code */ + odpl->activate_func(od); + + read_persistent_clock(&b); + + c = timespec_sub(b, a); + act_lat = timespec_to_ns(&c); + + dev_dbg(&od->pdev->dev, + "omap_device: pm_lat %d: activate: elapsed time %llu nsec\n", + od->pm_lat_level, act_lat); + + if (act_lat > odpl->activate_lat) { + odpl->activate_lat_worst = act_lat; + if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { + odpl->activate_lat = act_lat; + dev_dbg(&od->pdev->dev, + "new worst case activate latency %d: %llu\n", + od->pm_lat_level, act_lat); + } else + dev_warn(&od->pdev->dev, + "activate latency %d higher than expected. (%llu > %d)\n", + od->pm_lat_level, act_lat, + odpl->activate_lat); + } + + od->dev_wakeup_lat -= odpl->activate_lat; + } + + return 0; +} + +/** + * _omap_device_deactivate - decrease device readiness + * @od: struct omap_device * + * @ignore_lat: decrease to latency target (0) or full inactivity (1)? + * + * Decrease readiness of omap_device @od (thus increasing device + * wakeup latency, but conserving power). If @ignore_lat is + * IGNORE_WAKEUP_LAT, make the omap_device fully inactive. Otherwise, + * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup + * latency is less than the requested maximum wakeup latency, step + * forwards in the omap_device_pm_latency table to ensure the device's + * maximum wakeup latency is less than or equal to the requested + * maximum wakeup latency. Returns 0. + */ +static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat) +{ + struct timespec a, b, c; + + dev_dbg(&od->pdev->dev, "omap_device: deactivating\n"); + + while (od->pm_lat_level < od->pm_lats_cnt) { + struct omap_device_pm_latency *odpl; + unsigned long long deact_lat = 0; + + odpl = od->pm_lats + od->pm_lat_level; + + if (!ignore_lat && + ((od->dev_wakeup_lat + odpl->activate_lat) > + od->_dev_wakeup_lat_limit)) + break; + + read_persistent_clock(&a); + + /* XXX check return code */ + odpl->deactivate_func(od); + + read_persistent_clock(&b); + + c = timespec_sub(b, a); + deact_lat = timespec_to_ns(&c); + + dev_dbg(&od->pdev->dev, + "omap_device: pm_lat %d: deactivate: elapsed time %llu nsec\n", + od->pm_lat_level, deact_lat); + + if (deact_lat > odpl->deactivate_lat) { + odpl->deactivate_lat_worst = deact_lat; + if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { + odpl->deactivate_lat = deact_lat; + dev_dbg(&od->pdev->dev, + "new worst case deactivate latency %d: %llu\n", + od->pm_lat_level, deact_lat); + } else + dev_warn(&od->pdev->dev, + "deactivate latency %d higher than expected. (%llu > %d)\n", + od->pm_lat_level, deact_lat, + odpl->deactivate_lat); + } + + od->dev_wakeup_lat += odpl->activate_lat; + + od->pm_lat_level++; + } + + return 0; +} + +static void _add_clkdev(struct omap_device *od, const char *clk_alias, + const char *clk_name) +{ + struct clk *r; + struct clk_lookup *l; + + if (!clk_alias || !clk_name) + return; + + dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name); + + r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias); + if (!IS_ERR(r)) { + dev_warn(&od->pdev->dev, + "alias %s already exists\n", clk_alias); + clk_put(r); + return; + } + + r = clk_get(NULL, clk_name); + if (IS_ERR(r)) { + dev_err(&od->pdev->dev, + "clk_get for %s failed\n", clk_name); + return; + } + + l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev->dev)); + if (!l) { + dev_err(&od->pdev->dev, + "clkdev_alloc for %s failed\n", clk_alias); + return; + } + + clkdev_add(l); +} + +/** + * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks + * and main clock + * @od: struct omap_device *od + * @oh: struct omap_hwmod *oh + * + * For the main clock and every optional clock present per hwmod per + * omap_device, this function adds an entry in the clkdev table of the + * form <dev-id=dev_name, con-id=role> if it does not exist already. + * + * The function is called from inside omap_device_build_ss(), after + * omap_device_register. + * + * This allows drivers to get a pointer to its optional clocks based on its role + * by calling clk_get(<dev*>, <role>). + * In the case of the main clock, a "fck" alias is used. + * + * No return value. + */ +static void _add_hwmod_clocks_clkdev(struct omap_device *od, + struct omap_hwmod *oh) +{ + int i; + + _add_clkdev(od, "fck", oh->main_clk); + + for (i = 0; i < oh->opt_clks_cnt; i++) + _add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk); +} + + +/** + * omap_device_build_from_dt - build an omap_device with multiple hwmods + * @pdev_name: name of the platform_device driver to use + * @pdev_id: this platform_device's connection ID + * @oh: ptr to the single omap_hwmod that backs this omap_device + * @pdata: platform_data ptr to associate with the platform_device + * @pdata_len: amount of memory pointed to by @pdata + * @pm_lats: pointer to a omap_device_pm_latency array for this device + * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats + * @is_early_device: should the device be registered as an early device or not + * + * Function for building an omap_device already registered from device-tree + * + * Returns 0 or PTR_ERR() on error. + */ +static int omap_device_build_from_dt(struct platform_device *pdev) +{ + struct omap_hwmod **hwmods; + struct omap_device *od; + struct omap_hwmod *oh; + struct device_node *node = pdev->dev.of_node; + const char *oh_name; + int oh_cnt, i, ret = 0; + + oh_cnt = of_property_count_strings(node, "ti,hwmods"); + if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) { + dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n"); + return -ENODEV; + } + + hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); + if (!hwmods) { + ret = -ENOMEM; + goto odbfd_exit; + } + + for (i = 0; i < oh_cnt; i++) { + of_property_read_string_index(node, "ti,hwmods", i, &oh_name); + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n", + oh_name); + ret = -EINVAL; + goto odbfd_exit1; + } + hwmods[i] = oh; + } + + od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0); + if (!od) { + dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n", + oh_name); + ret = PTR_ERR(od); + goto odbfd_exit1; + } + + /* Fix up missing resource names */ + for (i = 0; i < pdev->num_resources; i++) { + struct resource *r = &pdev->resource[i]; + + if (r->name == NULL) + r->name = dev_name(&pdev->dev); + } + + if (of_get_property(node, "ti,no_idle_on_suspend", NULL)) + omap_device_disable_idle_on_suspend(pdev); + + pdev->dev.pm_domain = &omap_device_pm_domain; + +odbfd_exit1: + kfree(hwmods); +odbfd_exit: + return ret; +} + +static int _omap_device_notifier_call(struct notifier_block *nb, + unsigned long event, void *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct omap_device *od; + + switch (event) { + case BUS_NOTIFY_DEL_DEVICE: + if (pdev->archdata.od) + omap_device_delete(pdev->archdata.od); + break; + case BUS_NOTIFY_ADD_DEVICE: + if (pdev->dev.of_node) + omap_device_build_from_dt(pdev); + /* fall through */ + default: + od = to_omap_device(pdev); + if (od) + od->_driver_status = event; + } + + return NOTIFY_DONE; +} + + +/* Public functions for use by core code */ + +/** + * omap_device_get_context_loss_count - get lost context count + * @od: struct omap_device * + * + * Using the primary hwmod, query the context loss count for this + * device. + * + * Callers should consider context for this device lost any time this + * function returns a value different than the value the caller got + * the last time it called this function. + * + * If any hwmods exist for the omap_device assoiated with @pdev, + * return the context loss counter for that hwmod, otherwise return + * zero. + */ +int omap_device_get_context_loss_count(struct platform_device *pdev) +{ + struct omap_device *od; + u32 ret = 0; + + od = to_omap_device(pdev); + + if (od->hwmods_cnt) + ret = omap_hwmod_get_context_loss_count(od->hwmods[0]); + + return ret; +} + +/** + * omap_device_count_resources - count number of struct resource entries needed + * @od: struct omap_device * + * + * Count the number of struct resource entries needed for this + * omap_device @od. Used by omap_device_build_ss() to determine how + * much memory to allocate before calling + * omap_device_fill_resources(). Returns the count. + */ +static int omap_device_count_resources(struct omap_device *od) +{ + int c = 0; + int i; + + for (i = 0; i < od->hwmods_cnt; i++) + c += omap_hwmod_count_resources(od->hwmods[i]); + + pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n", + od->pdev->name, c, od->hwmods_cnt); + + return c; +} + +/** + * omap_device_fill_resources - fill in array of struct resource + * @od: struct omap_device * + * @res: pointer to an array of struct resource to be filled in + * + * Populate one or more empty struct resource pointed to by @res with + * the resource data for this omap_device @od. Used by + * omap_device_build_ss() after calling omap_device_count_resources(). + * Ideally this function would not be needed at all. If omap_device + * replaces platform_device, then we can specify our own + * get_resource()/ get_irq()/etc functions that use the underlying + * omap_hwmod information. Or if platform_device is extended to use + * subarchitecture-specific function pointers, the various + * platform_device functions can simply call omap_device internal + * functions to get device resources. Hacking around the existing + * platform_device code wastes memory. Returns 0. + */ +static int omap_device_fill_resources(struct omap_device *od, + struct resource *res) +{ + int i, r; + + for (i = 0; i < od->hwmods_cnt; i++) { + r = omap_hwmod_fill_resources(od->hwmods[i], res); + res += r; + } + + return 0; +} + +/** + * _od_fill_dma_resources - fill in array of struct resource with dma resources + * @od: struct omap_device * + * @res: pointer to an array of struct resource to be filled in + * + * Populate one or more empty struct resource pointed to by @res with + * the dma resource data for this omap_device @od. Used by + * omap_device_alloc() after calling omap_device_count_resources(). + * + * Ideally this function would not be needed at all. If we have + * mechanism to get dma resources from DT. + * + * Returns 0. + */ +static int _od_fill_dma_resources(struct omap_device *od, + struct resource *res) +{ + int i, r; + + for (i = 0; i < od->hwmods_cnt; i++) { + r = omap_hwmod_fill_dma_resources(od->hwmods[i], res); + res += r; + } + + return 0; +} + +/** + * omap_device_alloc - allocate an omap_device + * @pdev: platform_device that will be included in this omap_device + * @oh: ptr to the single omap_hwmod that backs this omap_device + * @pdata: platform_data ptr to associate with the platform_device + * @pdata_len: amount of memory pointed to by @pdata + * @pm_lats: pointer to a omap_device_pm_latency array for this device + * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats + * + * Convenience function for allocating an omap_device structure and filling + * hwmods, resources and pm_latency attributes. + * + * Returns an struct omap_device pointer or ERR_PTR() on error; + */ +struct omap_device *omap_device_alloc(struct platform_device *pdev, + struct omap_hwmod **ohs, int oh_cnt, + struct omap_device_pm_latency *pm_lats, + int pm_lats_cnt) +{ + int ret = -ENOMEM; + struct omap_device *od; + struct resource *res = NULL; + int i, res_count; + struct omap_hwmod **hwmods; + + od = kzalloc(sizeof(struct omap_device), GFP_KERNEL); + if (!od) { + ret = -ENOMEM; + goto oda_exit1; + } + od->hwmods_cnt = oh_cnt; + + hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); + if (!hwmods) + goto oda_exit2; + + od->hwmods = hwmods; + od->pdev = pdev; + + res_count = omap_device_count_resources(od); + /* + * DT Boot: + * OF framework will construct the resource structure (currently + * does for MEM & IRQ resource) and we should respect/use these + * resources, killing hwmod dependency. + * If pdev->num_resources > 0, we assume that MEM & IRQ resources + * have been allocated by OF layer already (through DTB). + * + * Non-DT Boot: + * Here, pdev->num_resources = 0, and we should get all the + * resources from hwmod. + * + * TODO: Once DMA resource is available from OF layer, we should + * kill filling any resources from hwmod. + */ + if (res_count > pdev->num_resources) { + /* Allocate resources memory to account for new resources */ + res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL); + if (!res) + goto oda_exit3; + + /* + * If pdev->num_resources > 0, then assume that, + * MEM and IRQ resources will only come from DT and only + * fill DMA resource from hwmod layer. + */ + if (pdev->num_resources && pdev->resource) { + dev_dbg(&pdev->dev, "%s(): resources already allocated %d\n", + __func__, res_count); + memcpy(res, pdev->resource, + sizeof(struct resource) * pdev->num_resources); + _od_fill_dma_resources(od, &res[pdev->num_resources]); + } else { + dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n", + __func__, res_count); + omap_device_fill_resources(od, res); + } + + ret = platform_device_add_resources(pdev, res, res_count); + kfree(res); + + if (ret) + goto oda_exit3; + } + + if (!pm_lats) { + pm_lats = omap_default_latency; + pm_lats_cnt = ARRAY_SIZE(omap_default_latency); + } + + od->pm_lats_cnt = pm_lats_cnt; + od->pm_lats = kmemdup(pm_lats, + sizeof(struct omap_device_pm_latency) * pm_lats_cnt, + GFP_KERNEL); + if (!od->pm_lats) + goto oda_exit3; + + pdev->archdata.od = od; + + for (i = 0; i < oh_cnt; i++) { + hwmods[i]->od = od; + _add_hwmod_clocks_clkdev(od, hwmods[i]); + } + + return od; + +oda_exit3: + kfree(hwmods); +oda_exit2: + kfree(od); +oda_exit1: + dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret); + + return ERR_PTR(ret); +} + +void omap_device_delete(struct omap_device *od) +{ + if (!od) + return; + + od->pdev->archdata.od = NULL; + kfree(od->pm_lats); + kfree(od->hwmods); + kfree(od); +} + +/** + * omap_device_build - build and register an omap_device with one omap_hwmod + * @pdev_name: name of the platform_device driver to use + * @pdev_id: this platform_device's connection ID + * @oh: ptr to the single omap_hwmod that backs this omap_device + * @pdata: platform_data ptr to associate with the platform_device + * @pdata_len: amount of memory pointed to by @pdata + * @pm_lats: pointer to a omap_device_pm_latency array for this device + * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats + * @is_early_device: should the device be registered as an early device or not + * + * Convenience function for building and registering a single + * omap_device record, which in turn builds and registers a + * platform_device record. See omap_device_build_ss() for more + * information. Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise, + * passes along the return value of omap_device_build_ss(). + */ +struct platform_device __init *omap_device_build(const char *pdev_name, int pdev_id, + struct omap_hwmod *oh, void *pdata, + int pdata_len, + struct omap_device_pm_latency *pm_lats, + int pm_lats_cnt, int is_early_device) +{ + struct omap_hwmod *ohs[] = { oh }; + + if (!oh) + return ERR_PTR(-EINVAL); + + return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata, + pdata_len, pm_lats, pm_lats_cnt, + is_early_device); +} + +/** + * omap_device_build_ss - build and register an omap_device with multiple hwmods + * @pdev_name: name of the platform_device driver to use + * @pdev_id: this platform_device's connection ID + * @oh: ptr to the single omap_hwmod that backs this omap_device + * @pdata: platform_data ptr to associate with the platform_device + * @pdata_len: amount of memory pointed to by @pdata + * @pm_lats: pointer to a omap_device_pm_latency array for this device + * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats + * @is_early_device: should the device be registered as an early device or not + * + * Convenience function for building and registering an omap_device + * subsystem record. Subsystem records consist of multiple + * omap_hwmods. This function in turn builds and registers a + * platform_device record. Returns an ERR_PTR() on error, or passes + * along the return value of omap_device_register(). + */ +struct platform_device __init *omap_device_build_ss(const char *pdev_name, int pdev_id, + struct omap_hwmod **ohs, int oh_cnt, + void *pdata, int pdata_len, + struct omap_device_pm_latency *pm_lats, + int pm_lats_cnt, int is_early_device) +{ + int ret = -ENOMEM; + struct platform_device *pdev; + struct omap_device *od; + + if (!ohs || oh_cnt == 0 || !pdev_name) + return ERR_PTR(-EINVAL); + + if (!pdata && pdata_len > 0) + return ERR_PTR(-EINVAL); + + pdev = platform_device_alloc(pdev_name, pdev_id); + if (!pdev) { + ret = -ENOMEM; + goto odbs_exit; + } + + /* Set the dev_name early to allow dev_xxx in omap_device_alloc */ + if (pdev->id != -1) + dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); + else + dev_set_name(&pdev->dev, "%s", pdev->name); + + od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt); + if (IS_ERR(od)) + goto odbs_exit1; + + ret = platform_device_add_data(pdev, pdata, pdata_len); + if (ret) + goto odbs_exit2; + + if (is_early_device) + ret = omap_early_device_register(pdev); + else + ret = omap_device_register(pdev); + if (ret) + goto odbs_exit2; + + return pdev; + +odbs_exit2: + omap_device_delete(od); +odbs_exit1: + platform_device_put(pdev); +odbs_exit: + + pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret); + + return ERR_PTR(ret); +} + +/** + * omap_early_device_register - register an omap_device as an early platform + * device. + * @od: struct omap_device * to register + * + * Register the omap_device structure. This currently just calls + * platform_early_add_device() on the underlying platform_device. + * Returns 0 by default. + */ +static int __init omap_early_device_register(struct platform_device *pdev) +{ + struct platform_device *devices[1]; + + devices[0] = pdev; + early_platform_add_devices(devices, 1); + return 0; +} + +#ifdef CONFIG_PM_RUNTIME +static int _od_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + int ret; + + ret = pm_generic_runtime_suspend(dev); + + if (!ret) + omap_device_idle(pdev); + + return ret; +} + +static int _od_runtime_idle(struct device *dev) +{ + return pm_generic_runtime_idle(dev); +} + +static int _od_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + omap_device_enable(pdev); + + return pm_generic_runtime_resume(dev); +} +#endif + +#ifdef CONFIG_SUSPEND +static int _od_suspend_noirq(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct omap_device *od = to_omap_device(pdev); + int ret; + + /* Don't attempt late suspend on a driver that is not bound */ + if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) + return 0; + + ret = pm_generic_suspend_noirq(dev); + + if (!ret && !pm_runtime_status_suspended(dev)) { + if (pm_generic_runtime_suspend(dev) == 0) { + if (!(od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)) + omap_device_idle(pdev); + od->flags |= OMAP_DEVICE_SUSPENDED; + } + } + + return ret; +} + +static int _od_resume_noirq(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct omap_device *od = to_omap_device(pdev); + + if ((od->flags & OMAP_DEVICE_SUSPENDED) && + !pm_runtime_status_suspended(dev)) { + od->flags &= ~OMAP_DEVICE_SUSPENDED; + if (!(od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)) + omap_device_enable(pdev); + pm_generic_runtime_resume(dev); + } + + return pm_generic_resume_noirq(dev); +} +#else +#define _od_suspend_noirq NULL +#define _od_resume_noirq NULL +#endif + +struct dev_pm_domain omap_device_pm_domain = { + .ops = { + SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume, + _od_runtime_idle) + USE_PLATFORM_PM_SLEEP_OPS + .suspend_noirq = _od_suspend_noirq, + .resume_noirq = _od_resume_noirq, + } +}; + +/** + * omap_device_register - register an omap_device with one omap_hwmod + * @od: struct omap_device * to register + * + * Register the omap_device structure. This currently just calls + * platform_device_register() on the underlying platform_device. + * Returns the return value of platform_device_register(). + */ +int omap_device_register(struct platform_device *pdev) +{ + pr_debug("omap_device: %s: registering\n", pdev->name); + + pdev->dev.pm_domain = &omap_device_pm_domain; + return platform_device_add(pdev); +} + + +/* Public functions for use by device drivers through struct platform_data */ + +/** + * omap_device_enable - fully activate an omap_device + * @od: struct omap_device * to activate + * + * Do whatever is necessary for the hwmods underlying omap_device @od + * to be accessible and ready to operate. This generally involves + * enabling clocks, setting SYSCONFIG registers; and in the future may + * involve remuxing pins. Device drivers should call this function + * (through platform_data function pointers) where they would normally + * enable clocks, etc. Returns -EINVAL if called when the omap_device + * is already enabled, or passes along the return value of + * _omap_device_activate(). + */ +int omap_device_enable(struct platform_device *pdev) +{ + int ret; + struct omap_device *od; + + od = to_omap_device(pdev); + + if (od->_state == OMAP_DEVICE_STATE_ENABLED) { + dev_warn(&pdev->dev, + "omap_device: %s() called from invalid state %d\n", + __func__, od->_state); + return -EINVAL; + } + + /* Enable everything if we're enabling this device from scratch */ + if (od->_state == OMAP_DEVICE_STATE_UNKNOWN) + od->pm_lat_level = od->pm_lats_cnt; + + ret = _omap_device_activate(od, IGNORE_WAKEUP_LAT); + + od->dev_wakeup_lat = 0; + od->_dev_wakeup_lat_limit = UINT_MAX; + od->_state = OMAP_DEVICE_STATE_ENABLED; + + return ret; +} + +/** + * omap_device_idle - idle an omap_device + * @od: struct omap_device * to idle + * + * Idle omap_device @od by calling as many .deactivate_func() entries + * in the omap_device's pm_lats table as is possible without exceeding + * the device's maximum wakeup latency limit, pm_lat_limit. Device + * drivers should call this function (through platform_data function + * pointers) where they would normally disable clocks after operations + * complete, etc.. Returns -EINVAL if the omap_device is not + * currently enabled, or passes along the return value of + * _omap_device_deactivate(). + */ +int omap_device_idle(struct platform_device *pdev) +{ + int ret; + struct omap_device *od; + + od = to_omap_device(pdev); + + if (od->_state != OMAP_DEVICE_STATE_ENABLED) { + dev_warn(&pdev->dev, + "omap_device: %s() called from invalid state %d\n", + __func__, od->_state); + return -EINVAL; + } + + ret = _omap_device_deactivate(od, USE_WAKEUP_LAT); + + od->_state = OMAP_DEVICE_STATE_IDLE; + + return ret; +} + +/** + * omap_device_shutdown - shut down an omap_device + * @od: struct omap_device * to shut down + * + * Shut down omap_device @od by calling all .deactivate_func() entries + * in the omap_device's pm_lats table and then shutting down all of + * the underlying omap_hwmods. Used when a device is being "removed" + * or a device driver is being unloaded. Returns -EINVAL if the + * omap_device is not currently enabled or idle, or passes along the + * return value of _omap_device_deactivate(). + */ +int omap_device_shutdown(struct platform_device *pdev) +{ + int ret, i; + struct omap_device *od; + + od = to_omap_device(pdev); + + if (od->_state != OMAP_DEVICE_STATE_ENABLED && + od->_state != OMAP_DEVICE_STATE_IDLE) { + dev_warn(&pdev->dev, + "omap_device: %s() called from invalid state %d\n", + __func__, od->_state); + return -EINVAL; + } + + ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT); + + for (i = 0; i < od->hwmods_cnt; i++) + omap_hwmod_shutdown(od->hwmods[i]); + + od->_state = OMAP_DEVICE_STATE_SHUTDOWN; + + return ret; +} + +/** + * omap_device_assert_hardreset - set a device's hardreset line + * @pdev: struct platform_device * to reset + * @name: const char * name of the reset line + * + * Set the hardreset line identified by @name on the IP blocks + * associated with the hwmods backing the platform_device @pdev. All + * of the hwmods associated with @pdev must have the same hardreset + * line linked to them for this to work. Passes along the return value + * of omap_hwmod_assert_hardreset() in the event of any failure, or + * returns 0 upon success. + */ +int omap_device_assert_hardreset(struct platform_device *pdev, const char *name) +{ + struct omap_device *od = to_omap_device(pdev); + int ret = 0; + int i; + + for (i = 0; i < od->hwmods_cnt; i++) { + ret = omap_hwmod_assert_hardreset(od->hwmods[i], name); + if (ret) + break; + } + + return ret; +} + +/** + * omap_device_deassert_hardreset - release a device's hardreset line + * @pdev: struct platform_device * to reset + * @name: const char * name of the reset line + * + * Release the hardreset line identified by @name on the IP blocks + * associated with the hwmods backing the platform_device @pdev. All + * of the hwmods associated with @pdev must have the same hardreset + * line linked to them for this to work. Passes along the return + * value of omap_hwmod_deassert_hardreset() in the event of any + * failure, or returns 0 upon success. + */ +int omap_device_deassert_hardreset(struct platform_device *pdev, + const char *name) +{ + struct omap_device *od = to_omap_device(pdev); + int ret = 0; + int i; + + for (i = 0; i < od->hwmods_cnt; i++) { + ret = omap_hwmod_deassert_hardreset(od->hwmods[i], name); + if (ret) + break; + } + + return ret; +} + +/** + * omap_device_align_pm_lat - activate/deactivate device to match wakeup lat lim + * @od: struct omap_device * + * + * When a device's maximum wakeup latency limit changes, call some of + * the .activate_func or .deactivate_func function pointers in the + * omap_device's pm_lats array to ensure that the device's maximum + * wakeup latency is less than or equal to the new latency limit. + * Intended to be called by OMAP PM code whenever a device's maximum + * wakeup latency limit changes (e.g., via + * omap_pm_set_dev_wakeup_lat()). Returns 0 if nothing needs to be + * done (e.g., if the omap_device is not currently idle, or if the + * wakeup latency is already current with the new limit) or passes + * along the return value of _omap_device_deactivate() or + * _omap_device_activate(). + */ +int omap_device_align_pm_lat(struct platform_device *pdev, + u32 new_wakeup_lat_limit) +{ + int ret = -EINVAL; + struct omap_device *od; + + od = to_omap_device(pdev); + + if (new_wakeup_lat_limit == od->dev_wakeup_lat) + return 0; + + od->_dev_wakeup_lat_limit = new_wakeup_lat_limit; + + if (od->_state != OMAP_DEVICE_STATE_IDLE) + return 0; + else if (new_wakeup_lat_limit > od->dev_wakeup_lat) + ret = _omap_device_deactivate(od, USE_WAKEUP_LAT); + else if (new_wakeup_lat_limit < od->dev_wakeup_lat) + ret = _omap_device_activate(od, USE_WAKEUP_LAT); + + return ret; +} + +/** + * omap_device_get_pwrdm - return the powerdomain * associated with @od + * @od: struct omap_device * + * + * Return the powerdomain associated with the first underlying + * omap_hwmod for this omap_device. Intended for use by core OMAP PM + * code. Returns NULL on error or a struct powerdomain * upon + * success. + */ +struct powerdomain *omap_device_get_pwrdm(struct omap_device *od) +{ + /* + * XXX Assumes that all omap_hwmod powerdomains are identical. + * This may not necessarily be true. There should be a sanity + * check in here to WARN() if any difference appears. + */ + if (!od->hwmods_cnt) + return NULL; + + return omap_hwmod_get_pwrdm(od->hwmods[0]); +} + +/** + * omap_device_get_mpu_rt_va - return the MPU's virtual addr for the hwmod base + * @od: struct omap_device * + * + * Return the MPU's virtual address for the base of the hwmod, from + * the ioremap() that the hwmod code does. Only valid if there is one + * hwmod associated with this device. Returns NULL if there are zero + * or more than one hwmods associated with this omap_device; + * otherwise, passes along the return value from + * omap_hwmod_get_mpu_rt_va(). + */ +void __iomem *omap_device_get_rt_va(struct omap_device *od) +{ + if (od->hwmods_cnt != 1) + return NULL; + + return omap_hwmod_get_mpu_rt_va(od->hwmods[0]); +} + +/** + * omap_device_get_by_hwmod_name() - convert a hwmod name to + * device pointer. + * @oh_name: name of the hwmod device + * + * Returns back a struct device * pointer associated with a hwmod + * device represented by a hwmod_name + */ +struct device *omap_device_get_by_hwmod_name(const char *oh_name) +{ + struct omap_hwmod *oh; + + if (!oh_name) { + WARN(1, "%s: no hwmod name!\n", __func__); + return ERR_PTR(-EINVAL); + } + + oh = omap_hwmod_lookup(oh_name); + if (IS_ERR_OR_NULL(oh)) { + WARN(1, "%s: no hwmod for %s\n", __func__, + oh_name); + return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV); + } + if (IS_ERR_OR_NULL(oh->od)) { + WARN(1, "%s: no omap_device for %s\n", __func__, + oh_name); + return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV); + } + + if (IS_ERR_OR_NULL(oh->od->pdev)) + return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV); + + return &oh->od->pdev->dev; +} +EXPORT_SYMBOL(omap_device_get_by_hwmod_name); + +/* + * Public functions intended for use in omap_device_pm_latency + * .activate_func and .deactivate_func function pointers + */ + +/** + * omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods + * @od: struct omap_device *od + * + * Enable all underlying hwmods. Returns 0. + */ +int omap_device_enable_hwmods(struct omap_device *od) +{ + int i; + + for (i = 0; i < od->hwmods_cnt; i++) + omap_hwmod_enable(od->hwmods[i]); + + /* XXX pass along return value here? */ + return 0; +} + +/** + * omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods + * @od: struct omap_device *od + * + * Idle all underlying hwmods. Returns 0. + */ +int omap_device_idle_hwmods(struct omap_device *od) +{ + int i; + + for (i = 0; i < od->hwmods_cnt; i++) + omap_hwmod_idle(od->hwmods[i]); + + /* XXX pass along return value here? */ + return 0; +} + +/** + * omap_device_disable_clocks - disable all main and interface clocks + * @od: struct omap_device *od + * + * Disable the main functional clock and interface clock for all of the + * omap_hwmods associated with the omap_device. Returns 0. + */ +int omap_device_disable_clocks(struct omap_device *od) +{ + int i; + + for (i = 0; i < od->hwmods_cnt; i++) + omap_hwmod_disable_clocks(od->hwmods[i]); + + /* XXX pass along return value here? */ + return 0; +} + +/** + * omap_device_enable_clocks - enable all main and interface clocks + * @od: struct omap_device *od + * + * Enable the main functional clock and interface clock for all of the + * omap_hwmods associated with the omap_device. Returns 0. + */ +int omap_device_enable_clocks(struct omap_device *od) +{ + int i; + + for (i = 0; i < od->hwmods_cnt; i++) + omap_hwmod_enable_clocks(od->hwmods[i]); + + /* XXX pass along return value here? */ + return 0; +} + +static struct notifier_block platform_nb = { + .notifier_call = _omap_device_notifier_call, +}; + +static int __init omap_device_init(void) +{ + bus_register_notifier(&platform_bus_type, &platform_nb); + return 0; +} +core_initcall(omap_device_init); + +/** + * omap_device_late_idle - idle devices without drivers + * @dev: struct device * associated with omap_device + * @data: unused + * + * Check the driver bound status of this device, and idle it + * if there is no driver attached. + */ +static int __init omap_device_late_idle(struct device *dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct omap_device *od = to_omap_device(pdev); + + if (!od) + return 0; + + /* + * If omap_device state is enabled, but has no driver bound, + * idle it. + */ + if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) { + if (od->_state == OMAP_DEVICE_STATE_ENABLED) { + dev_warn(dev, "%s: enabled but no driver. Idling\n", + __func__); + omap_device_idle(pdev); + } + } + + return 0; +} + +static int __init omap_device_late_init(void) +{ + bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle); + return 0; +} +late_initcall(omap_device_late_init); diff --git a/arch/arm/mach-omap2/omap_device.h b/arch/arm/mach-omap2/omap_device.h new file mode 100644 index 000000000000..0933c599bf89 --- /dev/null +++ b/arch/arm/mach-omap2/omap_device.h @@ -0,0 +1,176 @@ +/* + * omap_device headers + * + * Copyright (C) 2009 Nokia Corporation + * Paul Walmsley + * + * Developed in collaboration with (alphabetical order): Benoit + * Cousson, Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram + * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard + * Woodruff + * + * 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. + * + * Eventually this type of functionality should either be + * a) implemented via arch-specific pointers in platform_device + * or + * b) implemented as a proper omap_bus/omap_device in Linux, no more + * platform_device + * + * omap_device differs from omap_hwmod in that it includes external + * (e.g., board- and system-level) integration details. omap_hwmod + * stores hardware data that is invariant for a given OMAP chip. + * + * To do: + * - GPIO integration + * - regulator integration + * + */ +#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_DEVICE_H +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_DEVICE_H + +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include "omap_hwmod.h" + +extern struct dev_pm_domain omap_device_pm_domain; + +/* omap_device._state values */ +#define OMAP_DEVICE_STATE_UNKNOWN 0 +#define OMAP_DEVICE_STATE_ENABLED 1 +#define OMAP_DEVICE_STATE_IDLE 2 +#define OMAP_DEVICE_STATE_SHUTDOWN 3 + +/* omap_device.flags values */ +#define OMAP_DEVICE_SUSPENDED BIT(0) +#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1) + +/** + * struct omap_device - omap_device wrapper for platform_devices + * @pdev: platform_device + * @hwmods: (one .. many per omap_device) + * @hwmods_cnt: ARRAY_SIZE() of @hwmods + * @pm_lats: ptr to an omap_device_pm_latency table + * @pm_lats_cnt: ARRAY_SIZE() of what is passed to @pm_lats + * @pm_lat_level: array index of the last odpl entry executed - -1 if never + * @dev_wakeup_lat: dev wakeup latency in nanoseconds + * @_dev_wakeup_lat_limit: dev wakeup latency limit in nsec - set by OMAP PM + * @_state: one of OMAP_DEVICE_STATE_* (see above) + * @flags: device flags + * @_driver_status: one of BUS_NOTIFY_*_DRIVER from <linux/device.h> + * + * Integrates omap_hwmod data into Linux platform_device. + * + * Field names beginning with underscores are for the internal use of + * the omap_device code. + * + */ +struct omap_device { + struct platform_device *pdev; + struct omap_hwmod **hwmods; + struct omap_device_pm_latency *pm_lats; + u32 dev_wakeup_lat; + u32 _dev_wakeup_lat_limit; + unsigned long _driver_status; + u8 pm_lats_cnt; + s8 pm_lat_level; + u8 hwmods_cnt; + u8 _state; + u8 flags; +}; + +/* Device driver interface (call via platform_data fn ptrs) */ + +int omap_device_enable(struct platform_device *pdev); +int omap_device_idle(struct platform_device *pdev); +int omap_device_shutdown(struct platform_device *pdev); + +/* Core code interface */ + +struct platform_device *omap_device_build(const char *pdev_name, int pdev_id, + struct omap_hwmod *oh, void *pdata, + int pdata_len, + struct omap_device_pm_latency *pm_lats, + int pm_lats_cnt, int is_early_device); + +struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id, + struct omap_hwmod **oh, int oh_cnt, + void *pdata, int pdata_len, + struct omap_device_pm_latency *pm_lats, + int pm_lats_cnt, int is_early_device); + +struct omap_device *omap_device_alloc(struct platform_device *pdev, + struct omap_hwmod **ohs, int oh_cnt, + struct omap_device_pm_latency *pm_lats, + int pm_lats_cnt); +void omap_device_delete(struct omap_device *od); +int omap_device_register(struct platform_device *pdev); + +void __iomem *omap_device_get_rt_va(struct omap_device *od); +struct device *omap_device_get_by_hwmod_name(const char *oh_name); + +/* OMAP PM interface */ +int omap_device_align_pm_lat(struct platform_device *pdev, + u32 new_wakeup_lat_limit); +struct powerdomain *omap_device_get_pwrdm(struct omap_device *od); +int omap_device_get_context_loss_count(struct platform_device *pdev); + +/* Other */ + +int omap_device_assert_hardreset(struct platform_device *pdev, + const char *name); +int omap_device_deassert_hardreset(struct platform_device *pdev, + const char *name); +int omap_device_idle_hwmods(struct omap_device *od); +int omap_device_enable_hwmods(struct omap_device *od); + +int omap_device_disable_clocks(struct omap_device *od); +int omap_device_enable_clocks(struct omap_device *od); + +/* + * Entries should be kept in latency order ascending + * + * deact_lat is the maximum number of microseconds required to complete + * deactivate_func() at the device's slowest OPP. + * + * act_lat is the maximum number of microseconds required to complete + * activate_func() at the device's slowest OPP. + * + * This will result in some suboptimal power management decisions at fast + * OPPs, but avoids having to recompute all device power management decisions + * if the system shifts from a fast OPP to a slow OPP (in order to meet + * latency requirements). + * + * XXX should deactivate_func/activate_func() take platform_device pointers + * rather than omap_device pointers? + */ +struct omap_device_pm_latency { + u32 deactivate_lat; + u32 deactivate_lat_worst; + int (*deactivate_func)(struct omap_device *od); + u32 activate_lat; + u32 activate_lat_worst; + int (*activate_func)(struct omap_device *od); + u32 flags; +}; + +#define OMAP_DEVICE_LATENCY_AUTO_ADJUST BIT(1) + +/* Get omap_device pointer from platform_device pointer */ +static inline struct omap_device *to_omap_device(struct platform_device *pdev) +{ + return pdev ? pdev->archdata.od : NULL; +} + +static inline +void omap_device_disable_idle_on_suspend(struct platform_device *pdev) +{ + struct omap_device *od = to_omap_device(pdev); + + od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND; +} + +#endif diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index b969ab1d258b..87eee3b62a3c 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -139,8 +139,8 @@ #include <linux/slab.h> #include <linux/bootmem.h> -#include <plat/clock.h> -#include <plat/omap_hwmod.h> +#include "clock.h" +#include "omap_hwmod.h" #include <plat/prcm.h> #include "soc.h" diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h new file mode 100644 index 000000000000..87b59b45c678 --- /dev/null +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -0,0 +1,675 @@ +/* + * omap_hwmod macros, structures + * + * Copyright (C) 2009-2011 Nokia Corporation + * Copyright (C) 2012 Texas Instruments, Inc. + * Paul Walmsley + * + * Created in collaboration with (alphabetical order): Benoît Cousson, + * Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram Pandita, Sakari + * Poussa, Anand Sawant, Santosh Shilimkar, Richard Woodruff + * + * 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. + * + * These headers and macros are used to define OMAP on-chip module + * data and their integration with other OMAP modules and Linux. + * Copious documentation and references can also be found in the + * omap_hwmod code, in arch/arm/mach-omap2/omap_hwmod.c (as of this + * writing). + * + * To do: + * - add interconnect error log structures + * - add pinmuxing + * - init_conn_id_bit (CONNID_BIT_VECTOR) + * - implement default hwmod SMS/SDRC flags? + * - move Linux-specific data ("non-ROM data") out + * + */ +#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/ioport.h> +#include <linux/spinlock.h> + +struct omap_device; + +extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type1; +extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2; +extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3; + +/* + * OCP SYSCONFIG bit shifts/masks TYPE1. These are for IPs compliant + * with the original PRCM protocol defined for OMAP2420 + */ +#define SYSC_TYPE1_MIDLEMODE_SHIFT 12 +#define SYSC_TYPE1_MIDLEMODE_MASK (0x3 << SYSC_TYPE1_MIDLEMODE_SHIFT) +#define SYSC_TYPE1_CLOCKACTIVITY_SHIFT 8 +#define SYSC_TYPE1_CLOCKACTIVITY_MASK (0x3 << SYSC_TYPE1_CLOCKACTIVITY_SHIFT) +#define SYSC_TYPE1_SIDLEMODE_SHIFT 3 +#define SYSC_TYPE1_SIDLEMODE_MASK (0x3 << SYSC_TYPE1_SIDLEMODE_SHIFT) +#define SYSC_TYPE1_ENAWAKEUP_SHIFT 2 +#define SYSC_TYPE1_ENAWAKEUP_MASK (1 << SYSC_TYPE1_ENAWAKEUP_SHIFT) +#define SYSC_TYPE1_SOFTRESET_SHIFT 1 +#define SYSC_TYPE1_SOFTRESET_MASK (1 << SYSC_TYPE1_SOFTRESET_SHIFT) +#define SYSC_TYPE1_AUTOIDLE_SHIFT 0 +#define SYSC_TYPE1_AUTOIDLE_MASK (1 << SYSC_TYPE1_AUTOIDLE_SHIFT) + +/* + * OCP SYSCONFIG bit shifts/masks TYPE2. These are for IPs compliant + * with the new PRCM protocol defined for new OMAP4 IPs. + */ +#define SYSC_TYPE2_SOFTRESET_SHIFT 0 +#define SYSC_TYPE2_SOFTRESET_MASK (1 << SYSC_TYPE2_SOFTRESET_SHIFT) +#define SYSC_TYPE2_SIDLEMODE_SHIFT 2 +#define SYSC_TYPE2_SIDLEMODE_MASK (0x3 << SYSC_TYPE2_SIDLEMODE_SHIFT) +#define SYSC_TYPE2_MIDLEMODE_SHIFT 4 +#define SYSC_TYPE2_MIDLEMODE_MASK (0x3 << SYSC_TYPE2_MIDLEMODE_SHIFT) +#define SYSC_TYPE2_DMADISABLE_SHIFT 16 +#define SYSC_TYPE2_DMADISABLE_MASK (0x1 << SYSC_TYPE2_DMADISABLE_SHIFT) + +/* + * OCP SYSCONFIG bit shifts/masks TYPE3. + * This is applicable for some IPs present in AM33XX + */ +#define SYSC_TYPE3_SIDLEMODE_SHIFT 0 +#define SYSC_TYPE3_SIDLEMODE_MASK (0x3 << SYSC_TYPE3_SIDLEMODE_SHIFT) +#define SYSC_TYPE3_MIDLEMODE_SHIFT 2 +#define SYSC_TYPE3_MIDLEMODE_MASK (0x3 << SYSC_TYPE3_MIDLEMODE_SHIFT) + +/* OCP SYSSTATUS bit shifts/masks */ +#define SYSS_RESETDONE_SHIFT 0 +#define SYSS_RESETDONE_MASK (1 << SYSS_RESETDONE_SHIFT) + +/* Master standby/slave idle mode flags */ +#define HWMOD_IDLEMODE_FORCE (1 << 0) +#define HWMOD_IDLEMODE_NO (1 << 1) +#define HWMOD_IDLEMODE_SMART (1 << 2) +#define HWMOD_IDLEMODE_SMART_WKUP (1 << 3) + +/* modulemode control type (SW or HW) */ +#define MODULEMODE_HWCTRL 1 +#define MODULEMODE_SWCTRL 2 + + +/** + * struct omap_hwmod_mux_info - hwmod specific mux configuration + * @pads: array of omap_device_pad entries + * @nr_pads: number of omap_device_pad entries + * + * Note that this is currently built during init as needed. + */ +struct omap_hwmod_mux_info { + int nr_pads; + struct omap_device_pad *pads; + int nr_pads_dynamic; + struct omap_device_pad **pads_dynamic; + int *irqs; + bool enabled; +}; + +/** + * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod + * @name: name of the IRQ channel (module local name) + * @irq: IRQ channel ID (should be non-negative except -1 = terminator) + * + * @name should be something short, e.g., "tx" or "rx". It is for use + * by platform_get_resource_byname(). It is defined locally to the + * hwmod. + */ +struct omap_hwmod_irq_info { + const char *name; + s16 irq; +}; + +/** + * struct omap_hwmod_dma_info - DMA channels used by the hwmod + * @name: name of the DMA channel (module local name) + * @dma_req: DMA request ID (should be non-negative except -1 = terminator) + * + * @name should be something short, e.g., "tx" or "rx". It is for use + * by platform_get_resource_byname(). It is defined locally to the + * hwmod. + */ +struct omap_hwmod_dma_info { + const char *name; + s16 dma_req; +}; + +/** + * struct omap_hwmod_rst_info - IPs reset lines use by hwmod + * @name: name of the reset line (module local name) + * @rst_shift: Offset of the reset bit + * @st_shift: Offset of the reset status bit (OMAP2/3 only) + * + * @name should be something short, e.g., "cpu0" or "rst". It is defined + * locally to the hwmod. + */ +struct omap_hwmod_rst_info { + const char *name; + u8 rst_shift; + u8 st_shift; +}; + +/** + * struct omap_hwmod_opt_clk - optional clocks used by this hwmod + * @role: "sys", "32k", "tv", etc -- for use in clk_get() + * @clk: opt clock: OMAP clock name + * @_clk: pointer to the struct clk (filled in at runtime) + * + * The module's interface clock and main functional clock should not + * be added as optional clocks. + */ +struct omap_hwmod_opt_clk { + const char *role; + const char *clk; + struct clk *_clk; +}; + + +/* omap_hwmod_omap2_firewall.flags bits */ +#define OMAP_FIREWALL_L3 (1 << 0) +#define OMAP_FIREWALL_L4 (1 << 1) + +/** + * struct omap_hwmod_omap2_firewall - OMAP2/3 device firewall data + * @l3_perm_bit: bit shift for L3_PM_*_PERMISSION_* + * @l4_fw_region: L4 firewall region ID + * @l4_prot_group: L4 protection group ID + * @flags: (see omap_hwmod_omap2_firewall.flags macros above) + */ +struct omap_hwmod_omap2_firewall { + u8 l3_perm_bit; + u8 l4_fw_region; + u8 l4_prot_group; + u8 flags; +}; + + +/* + * omap_hwmod_addr_space.flags bits + * + * ADDR_MAP_ON_INIT: Map this address space during omap_hwmod init. + * ADDR_TYPE_RT: Address space contains module register target data. + */ +#define ADDR_MAP_ON_INIT (1 << 0) /* XXX does not belong */ +#define ADDR_TYPE_RT (1 << 1) + +/** + * struct omap_hwmod_addr_space - address space handled by the hwmod + * @name: name of the address space + * @pa_start: starting physical address + * @pa_end: ending physical address + * @flags: (see omap_hwmod_addr_space.flags macros above) + * + * Address space doesn't necessarily follow physical interconnect + * structure. GPMC is one example. + */ +struct omap_hwmod_addr_space { + const char *name; + u32 pa_start; + u32 pa_end; + u8 flags; +}; + + +/* + * omap_hwmod_ocp_if.user bits: these indicate the initiators that use this + * interface to interact with the hwmod. Used to add sleep dependencies + * when the module is enabled or disabled. + */ +#define OCP_USER_MPU (1 << 0) +#define OCP_USER_SDMA (1 << 1) +#define OCP_USER_DSP (1 << 2) +#define OCP_USER_IVA (1 << 3) + +/* omap_hwmod_ocp_if.flags bits */ +#define OCPIF_SWSUP_IDLE (1 << 0) +#define OCPIF_CAN_BURST (1 << 1) + +/* omap_hwmod_ocp_if._int_flags possibilities */ +#define _OCPIF_INT_FLAGS_REGISTERED (1 << 0) + + +/** + * struct omap_hwmod_ocp_if - OCP interface data + * @master: struct omap_hwmod that initiates OCP transactions on this link + * @slave: struct omap_hwmod that responds to OCP transactions on this link + * @addr: address space associated with this link + * @clk: interface clock: OMAP clock name + * @_clk: pointer to the interface struct clk (filled in at runtime) + * @fw: interface firewall data + * @width: OCP data width + * @user: initiators using this interface (see OCP_USER_* macros above) + * @flags: OCP interface flags (see OCPIF_* macros above) + * @_int_flags: internal flags (see _OCPIF_INT_FLAGS* macros above) + * + * It may also be useful to add a tag_cnt field for OCP2.x devices. + * + * Parameter names beginning with an underscore are managed internally by + * the omap_hwmod code and should not be set during initialization. + */ +struct omap_hwmod_ocp_if { + struct omap_hwmod *master; + struct omap_hwmod *slave; + struct omap_hwmod_addr_space *addr; + const char *clk; + struct clk *_clk; + union { + struct omap_hwmod_omap2_firewall omap2; + } fw; + u8 width; + u8 user; + u8 flags; + u8 _int_flags; +}; + + +/* Macros for use in struct omap_hwmod_sysconfig */ + +/* Flags for use in omap_hwmod_sysconfig.idlemodes */ +#define MASTER_STANDBY_SHIFT 4 +#define SLAVE_IDLE_SHIFT 0 +#define SIDLE_FORCE (HWMOD_IDLEMODE_FORCE << SLAVE_IDLE_SHIFT) +#define SIDLE_NO (HWMOD_IDLEMODE_NO << SLAVE_IDLE_SHIFT) +#define SIDLE_SMART (HWMOD_IDLEMODE_SMART << SLAVE_IDLE_SHIFT) +#define SIDLE_SMART_WKUP (HWMOD_IDLEMODE_SMART_WKUP << SLAVE_IDLE_SHIFT) +#define MSTANDBY_FORCE (HWMOD_IDLEMODE_FORCE << MASTER_STANDBY_SHIFT) +#define MSTANDBY_NO (HWMOD_IDLEMODE_NO << MASTER_STANDBY_SHIFT) +#define MSTANDBY_SMART (HWMOD_IDLEMODE_SMART << MASTER_STANDBY_SHIFT) +#define MSTANDBY_SMART_WKUP (HWMOD_IDLEMODE_SMART_WKUP << MASTER_STANDBY_SHIFT) + +/* omap_hwmod_sysconfig.sysc_flags capability flags */ +#define SYSC_HAS_AUTOIDLE (1 << 0) +#define SYSC_HAS_SOFTRESET (1 << 1) +#define SYSC_HAS_ENAWAKEUP (1 << 2) +#define SYSC_HAS_EMUFREE (1 << 3) +#define SYSC_HAS_CLOCKACTIVITY (1 << 4) +#define SYSC_HAS_SIDLEMODE (1 << 5) +#define SYSC_HAS_MIDLEMODE (1 << 6) +#define SYSS_HAS_RESET_STATUS (1 << 7) +#define SYSC_NO_CACHE (1 << 8) /* XXX SW flag, belongs elsewhere */ +#define SYSC_HAS_RESET_STATUS (1 << 9) +#define SYSC_HAS_DMADISABLE (1 << 10) + +/* omap_hwmod_sysconfig.clockact flags */ +#define CLOCKACT_TEST_BOTH 0x0 +#define CLOCKACT_TEST_MAIN 0x1 +#define CLOCKACT_TEST_ICLK 0x2 +#define CLOCKACT_TEST_NONE 0x3 + +/** + * struct omap_hwmod_sysc_fields - hwmod OCP_SYSCONFIG register field offsets. + * @midle_shift: Offset of the midle bit + * @clkact_shift: Offset of the clockactivity bit + * @sidle_shift: Offset of the sidle bit + * @enwkup_shift: Offset of the enawakeup bit + * @srst_shift: Offset of the softreset bit + * @autoidle_shift: Offset of the autoidle bit + * @dmadisable_shift: Offset of the dmadisable bit + */ +struct omap_hwmod_sysc_fields { + u8 midle_shift; + u8 clkact_shift; + u8 sidle_shift; + u8 enwkup_shift; + u8 srst_shift; + u8 autoidle_shift; + u8 dmadisable_shift; +}; + +/** + * struct omap_hwmod_class_sysconfig - hwmod class OCP_SYS* data + * @rev_offs: IP block revision register offset (from module base addr) + * @sysc_offs: OCP_SYSCONFIG register offset (from module base addr) + * @syss_offs: OCP_SYSSTATUS register offset (from module base addr) + * @srst_udelay: Delay needed after doing a softreset in usecs + * @idlemodes: One or more of {SIDLE,MSTANDBY}_{OFF,FORCE,SMART} + * @sysc_flags: SYS{C,S}_HAS* flags indicating SYSCONFIG bits supported + * @clockact: the default value of the module CLOCKACTIVITY bits + * + * @clockact describes to the module which clocks are likely to be + * disabled when the PRCM issues its idle request to the module. Some + * modules have separate clockdomains for the interface clock and main + * functional clock, and can check whether they should acknowledge the + * idle request based on the internal module functionality that has + * been associated with the clocks marked in @clockact. This field is + * only used if HWMOD_SET_DEFAULT_CLOCKACT is set (see below) + * + * @sysc_fields: structure containing the offset positions of various bits in + * SYSCONFIG register. This can be populated using omap_hwmod_sysc_type1 or + * omap_hwmod_sysc_type2 defined in omap_hwmod_common_data.c depending on + * whether the device ip is compliant with the original PRCM protocol + * defined for OMAP2420 or the new PRCM protocol for new OMAP4 IPs. + * If the device follows a different scheme for the sysconfig register , + * then this field has to be populated with the correct offset structure. + */ +struct omap_hwmod_class_sysconfig { + u32 rev_offs; + u32 sysc_offs; + u32 syss_offs; + u16 sysc_flags; + struct omap_hwmod_sysc_fields *sysc_fields; + u8 srst_udelay; + u8 idlemodes; + u8 clockact; +}; + +/** + * struct omap_hwmod_omap2_prcm - OMAP2/3-specific PRCM data + * @module_offs: PRCM submodule offset from the start of the PRM/CM + * @prcm_reg_id: PRCM register ID (e.g., 3 for CM_AUTOIDLE3) + * @module_bit: register bit shift for AUTOIDLE, WKST, WKEN, GRPSEL regs + * @idlest_reg_id: IDLEST register ID (e.g., 3 for CM_IDLEST3) + * @idlest_idle_bit: register bit shift for CM_IDLEST slave idle bit + * @idlest_stdby_bit: register bit shift for CM_IDLEST master standby bit + * + * @prcm_reg_id and @module_bit are specific to the AUTOIDLE, WKST, + * WKEN, GRPSEL registers. In an ideal world, no extra information + * would be needed for IDLEST information, but alas, there are some + * exceptions, so @idlest_reg_id, @idlest_idle_bit, @idlest_stdby_bit + * are needed for the IDLEST registers (c.f. 2430 I2CHS, 3430 USBHOST) + */ +struct omap_hwmod_omap2_prcm { + s16 module_offs; + u8 prcm_reg_id; + u8 module_bit; + u8 idlest_reg_id; + u8 idlest_idle_bit; + u8 idlest_stdby_bit; +}; + +/* + * Possible values for struct omap_hwmod_omap4_prcm.flags + * + * HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT: Some IP blocks don't have a PRCM + * module-level context loss register associated with them; this + * flag bit should be set in those cases + */ +#define HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT (1 << 0) + +/** + * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data + * @clkctrl_reg: PRCM address of the clock control register + * @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM + * @lostcontext_mask: bitmask for selecting bits from RM_*_CONTEXT register + * @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM + * @submodule_wkdep_bit: bit shift of the WKDEP range + * @flags: PRCM register capabilities for this IP block + * + * If @lostcontext_mask is not defined, context loss check code uses + * whole register without masking. @lostcontext_mask should only be + * defined in cases where @context_offs register is shared by two or + * more hwmods. + */ +struct omap_hwmod_omap4_prcm { + u16 clkctrl_offs; + u16 rstctrl_offs; + u16 rstst_offs; + u16 context_offs; + u32 lostcontext_mask; + u8 submodule_wkdep_bit; + u8 modulemode; + u8 flags; +}; + + +/* + * omap_hwmod.flags definitions + * + * HWMOD_SWSUP_SIDLE: omap_hwmod code should manually bring module in and out + * of idle, rather than relying on module smart-idle + * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out + * of standby, rather than relying on module smart-standby + * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for + * SDRAM controller, etc. XXX probably belongs outside the main hwmod file + * XXX Should be HWMOD_SETUP_NO_RESET + * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM + * controller, etc. XXX probably belongs outside the main hwmod file + * XXX Should be HWMOD_SETUP_NO_IDLE + * HWMOD_NO_OCP_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE) + * when module is enabled, rather than the default, which is to + * enable autoidle + * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup + * HWMOD_NO_IDLEST: this module does not have idle status - this is the case + * only for few initiator modules on OMAP2 & 3. + * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset. + * This is needed for devices like DSS that require optional clocks enabled + * in order to complete the reset. Optional clocks will be disabled + * again after the reset. + * HWMOD_16BIT_REG: Module has 16bit registers + */ +#define HWMOD_SWSUP_SIDLE (1 << 0) +#define HWMOD_SWSUP_MSTANDBY (1 << 1) +#define HWMOD_INIT_NO_RESET (1 << 2) +#define HWMOD_INIT_NO_IDLE (1 << 3) +#define HWMOD_NO_OCP_AUTOIDLE (1 << 4) +#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5) +#define HWMOD_NO_IDLEST (1 << 6) +#define HWMOD_CONTROL_OPT_CLKS_IN_RESET (1 << 7) +#define HWMOD_16BIT_REG (1 << 8) + +/* + * omap_hwmod._int_flags definitions + * These are for internal use only and are managed by the omap_hwmod code. + * + * _HWMOD_NO_MPU_PORT: no path exists for the MPU to write to this module + * _HWMOD_WAKEUP_ENABLED: set when the omap_hwmod code has enabled ENAWAKEUP + * _HWMOD_SYSCONFIG_LOADED: set when the OCP_SYSCONFIG value has been cached + * _HWMOD_SKIP_ENABLE: set if hwmod enabled during init (HWMOD_INIT_NO_IDLE) - + * causes the first call to _enable() to only update the pinmux + */ +#define _HWMOD_NO_MPU_PORT (1 << 0) +#define _HWMOD_WAKEUP_ENABLED (1 << 1) +#define _HWMOD_SYSCONFIG_LOADED (1 << 2) +#define _HWMOD_SKIP_ENABLE (1 << 3) + +/* + * omap_hwmod._state definitions + * + * INITIALIZED: reset (optionally), initialized, enabled, disabled + * (optionally) + * + * + */ +#define _HWMOD_STATE_UNKNOWN 0 +#define _HWMOD_STATE_REGISTERED 1 +#define _HWMOD_STATE_CLKS_INITED 2 +#define _HWMOD_STATE_INITIALIZED 3 +#define _HWMOD_STATE_ENABLED 4 +#define _HWMOD_STATE_IDLE 5 +#define _HWMOD_STATE_DISABLED 6 + +/** + * struct omap_hwmod_class - the type of an IP block + * @name: name of the hwmod_class + * @sysc: device SYSCONFIG/SYSSTATUS register data + * @rev: revision of the IP class + * @pre_shutdown: ptr to fn to be executed immediately prior to device shutdown + * @reset: ptr to fn to be executed in place of the standard hwmod reset fn + * + * Represent the class of a OMAP hardware "modules" (e.g. timer, + * smartreflex, gpio, uart...) + * + * @pre_shutdown is a function that will be run immediately before + * hwmod clocks are disabled, etc. It is intended for use for hwmods + * like the MPU watchdog, which cannot be disabled with the standard + * omap_hwmod_shutdown(). The function should return 0 upon success, + * or some negative error upon failure. Returning an error will cause + * omap_hwmod_shutdown() to abort the device shutdown and return an + * error. + * + * If @reset is defined, then the function it points to will be + * executed in place of the standard hwmod _reset() code in + * mach-omap2/omap_hwmod.c. This is needed for IP blocks which have + * unusual reset sequences - usually processor IP blocks like the IVA. + */ +struct omap_hwmod_class { + const char *name; + struct omap_hwmod_class_sysconfig *sysc; + u32 rev; + int (*pre_shutdown)(struct omap_hwmod *oh); + int (*reset)(struct omap_hwmod *oh); +}; + +/** + * struct omap_hwmod_link - internal structure linking hwmods with ocp_ifs + * @ocp_if: OCP interface structure record pointer + * @node: list_head pointing to next struct omap_hwmod_link in a list + */ +struct omap_hwmod_link { + struct omap_hwmod_ocp_if *ocp_if; + struct list_head node; +}; + +/** + * struct omap_hwmod - integration data for OMAP hardware "modules" (IP blocks) + * @name: name of the hwmod + * @class: struct omap_hwmod_class * to the class of this hwmod + * @od: struct omap_device currently associated with this hwmod (internal use) + * @mpu_irqs: ptr to an array of MPU IRQs + * @sdma_reqs: ptr to an array of System DMA request IDs + * @prcm: PRCM data pertaining to this hwmod + * @main_clk: main clock: OMAP clock name + * @_clk: pointer to the main struct clk (filled in at runtime) + * @opt_clks: other device clocks that drivers can request (0..*) + * @voltdm: pointer to voltage domain (filled in at runtime) + * @dev_attr: arbitrary device attributes that can be passed to the driver + * @_sysc_cache: internal-use hwmod flags + * @_mpu_rt_va: cached register target start address (internal use) + * @_mpu_port: cached MPU register target slave (internal use) + * @opt_clks_cnt: number of @opt_clks + * @master_cnt: number of @master entries + * @slaves_cnt: number of @slave entries + * @response_lat: device OCP response latency (in interface clock cycles) + * @_int_flags: internal-use hwmod flags + * @_state: internal-use hwmod state + * @_postsetup_state: internal-use state to leave the hwmod in after _setup() + * @flags: hwmod flags (documented below) + * @_lock: spinlock serializing operations on this hwmod + * @node: list node for hwmod list (internal use) + * + * @main_clk refers to this module's "main clock," which for our + * purposes is defined as "the functional clock needed for register + * accesses to complete." Modules may not have a main clock if the + * interface clock also serves as a main clock. + * + * Parameter names beginning with an underscore are managed internally by + * the omap_hwmod code and should not be set during initialization. + * + * @masters and @slaves are now deprecated. + */ +struct omap_hwmod { + const char *name; + struct omap_hwmod_class *class; + struct omap_device *od; + struct omap_hwmod_mux_info *mux; + struct omap_hwmod_irq_info *mpu_irqs; + struct omap_hwmod_dma_info *sdma_reqs; + struct omap_hwmod_rst_info *rst_lines; + union { + struct omap_hwmod_omap2_prcm omap2; + struct omap_hwmod_omap4_prcm omap4; + } prcm; + const char *main_clk; + struct clk *_clk; + struct omap_hwmod_opt_clk *opt_clks; + char *clkdm_name; + struct clockdomain *clkdm; + struct list_head master_ports; /* connect to *_IA */ + struct list_head slave_ports; /* connect to *_TA */ + void *dev_attr; + u32 _sysc_cache; + void __iomem *_mpu_rt_va; + spinlock_t _lock; + struct list_head node; + struct omap_hwmod_ocp_if *_mpu_port; + u16 flags; + u8 response_lat; + u8 rst_lines_cnt; + u8 opt_clks_cnt; + u8 masters_cnt; + u8 slaves_cnt; + u8 hwmods_cnt; + u8 _int_flags; + u8 _state; + u8 _postsetup_state; +}; + +struct omap_hwmod *omap_hwmod_lookup(const char *name); +int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), + void *data); + +int __init omap_hwmod_setup_one(const char *name); + +int omap_hwmod_enable(struct omap_hwmod *oh); +int omap_hwmod_idle(struct omap_hwmod *oh); +int omap_hwmod_shutdown(struct omap_hwmod *oh); + +int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name); +int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name); +int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name); + +int omap_hwmod_enable_clocks(struct omap_hwmod *oh); +int omap_hwmod_disable_clocks(struct omap_hwmod *oh); + +int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode); +int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle); + +int omap_hwmod_reset(struct omap_hwmod *oh); +void omap_hwmod_ocp_barrier(struct omap_hwmod *oh); + +void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs); +u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs); +int omap_hwmod_softreset(struct omap_hwmod *oh); + +int omap_hwmod_count_resources(struct omap_hwmod *oh); +int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res); +int omap_hwmod_fill_dma_resources(struct omap_hwmod *oh, struct resource *res); +int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type, + const char *name, struct resource *res); + +struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh); +void __iomem *omap_hwmod_get_mpu_rt_va(struct omap_hwmod *oh); + +int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh, + struct omap_hwmod *init_oh); +int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh, + struct omap_hwmod *init_oh); + +int omap_hwmod_enable_wakeup(struct omap_hwmod *oh); +int omap_hwmod_disable_wakeup(struct omap_hwmod *oh); + +int omap_hwmod_for_each_by_class(const char *classname, + int (*fn)(struct omap_hwmod *oh, + void *user), + void *user); + +int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state); +int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh); + +int omap_hwmod_no_setup_reset(struct omap_hwmod *oh); + +int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx); + +extern void __init omap_hwmod_init(void); + +const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh); + +/* + * Chip variant-specific hwmod init routines - XXX should be converted + * to use initcalls once the initial boot ordering is straightened out + */ +extern int omap2420_hwmod_init(void); +extern int omap2430_hwmod_init(void); +extern int omap3xxx_hwmod_init(void); +extern int omap44xx_hwmod_init(void); +extern int am33xx_hwmod_init(void); + +extern int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois); + +#endif diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index b5db6007c523..3efed3d633d1 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -12,21 +12,23 @@ * XXX handle crossbar/shared link difference for L3? * XXX these should be marked initdata for multi-OMAP kernels */ + +#include <linux/i2c-omap.h> #include <linux/platform_data/spi-omap2-mcspi.h> -#include <plat/omap_hwmod.h> -#include <plat/dma.h> -#include <plat/serial.h> -#include <plat/i2c.h> +#include <plat-omap/dma-omap.h> #include <plat/dmtimer.h> + +#include "omap_hwmod.h" #include "l3_2xxx.h" #include "l4_2xxx.h" -#include <plat/mmc.h> #include "omap_hwmod_common_data.h" #include "cm-regbits-24xx.h" #include "prm-regbits-24xx.h" +#include "i2c.h" +#include "mmc.h" #include "wd_timer.h" /* diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index c455e41b0237..dc768c50e523 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -12,21 +12,23 @@ * XXX handle crossbar/shared link difference for L3? * XXX these should be marked initdata for multi-OMAP kernels */ + +#include <linux/i2c-omap.h> #include <linux/platform_data/asoc-ti-mcbsp.h> #include <linux/platform_data/spi-omap2-mcspi.h> -#include <plat/omap_hwmod.h> -#include <plat/dma.h> -#include <plat/serial.h> -#include <plat/i2c.h> +#include <plat-omap/dma-omap.h> #include <plat/dmtimer.h> -#include <plat/mmc.h> + +#include "omap_hwmod.h" +#include "mmc.h" #include "l3_2xxx.h" #include "soc.h" #include "omap_hwmod_common_data.h" #include "prm-regbits-24xx.h" #include "cm-regbits-24xx.h" +#include "i2c.h" #include "wd_timer.h" /* diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c index cbb4ef6544ad..74ae76767510 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c @@ -13,9 +13,10 @@ */ #include <asm/sizes.h> -#include <plat/omap_hwmod.h> #include <plat/serial.h> +#include "omap_hwmod.h" + #include "omap_hwmod_common_data.h" struct omap_hwmod_addr_space omap2430_mmc1_addr_space[] = { diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c index 8851bbb6bb24..57fc2f95584d 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c @@ -9,13 +9,17 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <plat/omap_hwmod.h> + #include <plat/serial.h> -#include <plat/dma.h> -#include <plat/common.h> +#include <plat-omap/dma-omap.h> + +#include "../plat-omap/common.h" + +#include "omap_hwmod.h" #include "hdq1w.h" #include "omap_hwmod_common_data.h" +#include "dma.h" /* UART */ diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c index 1a1287d62648..dd3809c8f409 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c @@ -13,8 +13,9 @@ */ #include <asm/sizes.h> -#include <plat/omap_hwmod.h> #include <plat/serial.h> + +#include "omap_hwmod.h" #include "l3_2xxx.h" #include "l4_2xxx.h" diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index bd9220ed5ab9..27bdff46fda0 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c @@ -8,13 +8,14 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <plat/omap_hwmod.h> + #include <plat/serial.h> #include <linux/platform_data/gpio-omap.h> -#include <plat/dma.h> +#include <plat-omap/dma-omap.h> #include <plat/dmtimer.h> #include <linux/platform_data/spi-omap2-mcspi.h> +#include "omap_hwmod.h" #include "omap_hwmod_common_data.h" #include "cm-regbits-24xx.h" #include "prm-regbits-24xx.h" diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c index 59d5c1cd316d..ad8d43b33273 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c @@ -14,13 +14,11 @@ * GNU General Public License for more details. */ -#include <plat/omap_hwmod.h> -#include <plat/cpu.h> +#include <linux/i2c-omap.h> + +#include "omap_hwmod.h" #include <linux/platform_data/gpio-omap.h> #include <linux/platform_data/spi-omap2-mcspi.h> -#include <plat/dma.h> -#include <plat/mmc.h> -#include <plat/i2c.h> #include "omap_hwmod_common_data.h" @@ -28,6 +26,8 @@ #include "cm33xx.h" #include "prm33xx.h" #include "prm-regbits-33xx.h" +#include "i2c.h" +#include "mmc.h" /* * IP blocks diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index f67b7ee07dd4..d5d52a776278 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -14,16 +14,16 @@ * * XXX these should be marked initdata for multi-OMAP kernels */ + +#include <linux/i2c-omap.h> #include <linux/power/smartreflex.h> #include <linux/platform_data/gpio-omap.h> -#include <plat/omap_hwmod.h> -#include <plat/dma.h> +#include <plat-omap/dma-omap.h> #include <plat/serial.h> + #include "l3_3xxx.h" #include "l4_3xxx.h" -#include <plat/i2c.h> -#include <plat/mmc.h> #include <linux/platform_data/asoc-ti-mcbsp.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <plat/dmtimer.h> @@ -32,9 +32,14 @@ #include "am35xx.h" #include "soc.h" +#include "omap_hwmod.h" #include "omap_hwmod_common_data.h" #include "prm-regbits-34xx.h" #include "cm-regbits-34xx.h" + +#include "dma.h" +#include "i2c.h" +#include "mmc.h" #include "wd_timer.h" /* diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 652d0285bd6d..5b9be734709c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -21,22 +21,25 @@ #include <linux/io.h> #include <linux/platform_data/gpio-omap.h> #include <linux/power/smartreflex.h> +#include <linux/i2c-omap.h> + +#include <plat-omap/dma-omap.h> -#include <plat/omap_hwmod.h> -#include <plat/i2c.h> -#include <plat/dma.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/platform_data/asoc-ti-mcbsp.h> -#include <plat/mmc.h> #include <plat/dmtimer.h> -#include <plat/common.h> #include <plat/iommu.h> +#include "../plat-omap/common.h" + +#include "omap_hwmod.h" #include "omap_hwmod_common_data.h" #include "cm1_44xx.h" #include "cm2_44xx.h" #include "prm44xx.h" #include "prm-regbits-44xx.h" +#include "i2c.h" +#include "mmc.h" #include "wd_timer.h" /* Base offset for all OMAP4 interrupts external to MPUSS */ diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c index 9f1ccdc8cc8c..79d623b83e49 100644 --- a/arch/arm/mach-omap2/omap_hwmod_common_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c @@ -16,7 +16,7 @@ * data and their integration with other OMAP modules and Linux. */ -#include <plat/omap_hwmod.h> +#include "omap_hwmod.h" #include "omap_hwmod_common_data.h" diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h index 2bc8f1705d4a..cfcce299177c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_common_data.h +++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h @@ -13,7 +13,7 @@ #ifndef __ARCH_ARM_MACH_OMAP2_OMAP_HWMOD_COMMON_DATA_H #define __ARCH_ARM_MACH_OMAP2_OMAP_HWMOD_COMMON_DATA_H -#include <plat/omap_hwmod.h> +#include "omap_hwmod.h" #include "common.h" #include "display.h" diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h index c784c12f98a1..7e437bf6024c 100644 --- a/arch/arm/mach-omap2/omap_opp_data.h +++ b/arch/arm/mach-omap2/omap_opp_data.h @@ -19,7 +19,7 @@ #ifndef __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H #define __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H -#include <plat/omap_hwmod.h> +#include "omap_hwmod.h" #include "voltage.h" diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c index f515a1a056d5..2bf35dc091be 100644 --- a/arch/arm/mach-omap2/omap_twl.c +++ b/arch/arm/mach-omap2/omap_twl.c @@ -18,6 +18,7 @@ #include <linux/kernel.h> #include <linux/i2c/twl.h> +#include "soc.h" #include "voltage.h" #include "pm.h" diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c index 58e16aef40bb..bd41d59a7cab 100644 --- a/arch/arm/mach-omap2/opp.c +++ b/arch/arm/mach-omap2/opp.c @@ -20,7 +20,7 @@ #include <linux/opp.h> #include <linux/cpu.h> -#include <plat/omap_device.h> +#include "omap_device.h" #include "omap_opp_data.h" diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c index 75cef5f67a8a..62772e0e0d69 100644 --- a/arch/arm/mach-omap2/opp3xxx_data.c +++ b/arch/arm/mach-omap2/opp3xxx_data.c @@ -19,6 +19,7 @@ */ #include <linux/module.h> +#include "soc.h" #include "control.h" #include "omap_opp_data.h" #include "pm.h" diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 46092cd806fa..3cf4fdfd7ab0 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -27,12 +27,13 @@ #include <linux/module.h> #include <linux/slab.h> -#include <plat/clock.h> +#include "clock.h" #include "powerdomain.h" #include "clockdomain.h" #include <plat/dmtimer.h> -#include <plat/omap-pm.h> +#include "omap-pm.h" +#include "soc.h" #include "cm2xxx_3xxx.h" #include "prm2xxx_3xxx.h" #include "pm.h" diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index ea61c32957bd..331478f9b864 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -20,10 +20,11 @@ #include <asm/system_misc.h> -#include <plat/omap-pm.h> -#include <plat/omap_device.h> +#include "omap-pm.h" +#include "omap_device.h" #include "common.h" +#include "soc.h" #include "prcm-common.h" #include "voltage.h" #include "powerdomain.h" diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 8af6cd6ac331..6d17e044ffb8 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -36,11 +36,13 @@ #include <asm/mach-types.h> #include <asm/system_misc.h> -#include <plat/clock.h> -#include <plat/sram.h> -#include <plat/dma.h> +#include <plat-omap/dma-omap.h> +#include "../plat-omap/sram.h" + +#include "soc.h" #include "common.h" +#include "clock.h" #include "prm2xxx_3xxx.h" #include "prm-regbits-24xx.h" #include "cm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index ba670db1fd37..160fa250c41e 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -35,17 +35,18 @@ #include <asm/suspend.h> #include <asm/system_misc.h> -#include <plat/sram.h> #include "clockdomain.h" #include "powerdomain.h" -#include <plat/sdrc.h> #include <plat/prcm.h> -#include <plat/gpmc.h> -#include <plat/dma.h> +#include <plat-omap/dma-omap.h> +#include "../plat-omap/sram.h" + +#include "soc.h" #include "common.h" #include "cm2xxx_3xxx.h" #include "cm-regbits-34xx.h" +#include "gpmc.h" #include "prm-regbits-34xx.h" #include "prm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 04922d149068..7da75aed1514 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -18,6 +18,7 @@ #include <linux/slab.h> #include <asm/system_misc.h> +#include "soc.h" #include "common.h" #include "clockdomain.h" #include "powerdomain.h" diff --git a/arch/arm/mach-omap2/pmu.c b/arch/arm/mach-omap2/pmu.c index 2a791766283d..3cf79b54ce61 100644 --- a/arch/arm/mach-omap2/pmu.c +++ b/arch/arm/mach-omap2/pmu.c @@ -15,8 +15,9 @@ #include <asm/pmu.h> -#include <plat/omap_hwmod.h> -#include <plat/omap_device.h> +#include "soc.h" +#include "omap_hwmod.h" +#include "omap_device.h" static char *omap2_pmu_oh_names[] = {"mpu"}; static char *omap3_pmu_oh_names[] = {"mpu", "debugss"}; diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index baee90608d11..5277d56eb37f 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -22,8 +22,6 @@ #include <linux/atomic.h> -#include <plat/cpu.h> - #include "voltage.h" /* Powerdomain basic power states */ diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c index 2385c1f009ee..ba520d4f7c7b 100644 --- a/arch/arm/mach-omap2/powerdomains2xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c @@ -14,6 +14,7 @@ #include <linux/kernel.h> #include <linux/init.h> +#include "soc.h" #include "powerdomain.h" #include "powerdomains2xxx_3xxx_data.h" diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c index 0f51e034e0aa..cff270a178c5 100644 --- a/arch/arm/mach-omap2/prcm.c +++ b/arch/arm/mach-omap2/prcm.c @@ -28,6 +28,7 @@ #include "common.h" #include <plat/prcm.h> +#include "soc.h" #include "clock.h" #include "clock2xxx.h" #include "cm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c index e7dbb6cf1255..624ade5c3c33 100644 --- a/arch/arm/mach-omap2/prm33xx.c +++ b/arch/arm/mach-omap2/prm33xx.c @@ -19,7 +19,7 @@ #include <linux/err.h> #include <linux/io.h> -#include <plat/common.h> +#include "../plat-omap/common.h" #include "common.h" #include "prm33xx.h" diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index 6b4d332be2f6..6fabbd816d6b 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -24,7 +24,7 @@ #include <linux/interrupt.h> #include <linux/slab.h> -#include <plat/common.h> +#include "../plat-omap/common.h" #include <plat/prcm.h> #include "prm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h b/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h index 8bfaf342a028..1ee58c281a31 100644 --- a/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h +++ b/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h @@ -11,7 +11,7 @@ #ifndef __ARCH_ARM_MACH_OMAP2_SDRAM_HYNIX_H8MBX00U0MER0EM #define __ARCH_ARM_MACH_OMAP2_SDRAM_HYNIX_H8MBX00U0MER0EM -#include <plat/sdrc.h> +#include "sdrc.h" /* Hynix H8MBX00U0MER-0EM */ static struct omap_sdrc_params h8mbx00u0mer0em_sdrc_params[] = { diff --git a/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h b/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h index a391b4939f74..85cccc004c06 100644 --- a/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h +++ b/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h @@ -14,7 +14,7 @@ #ifndef ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF #define ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF -#include <plat/sdrc.h> +#include "sdrc.h" /* Micron MT46H32M32LF-6 */ /* XXX Using ARE = 0x1 (no autorefresh burst) -- can this be changed? */ diff --git a/arch/arm/mach-omap2/sdram-nokia.c b/arch/arm/mach-omap2/sdram-nokia.c index 845c4fd2b125..0fa7ffa9b5ed 100644 --- a/arch/arm/mach-omap2/sdram-nokia.c +++ b/arch/arm/mach-omap2/sdram-nokia.c @@ -18,10 +18,8 @@ #include <linux/io.h> #include "common.h" -#include <plat/clock.h> -#include <plat/sdrc.h> - #include "sdram-nokia.h" +#include "sdrc.h" /* In picoseconds, except for tREF (ns), tXP, tCKE, tWTR (clks) */ struct sdram_timings { diff --git a/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h b/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h index cd4352917022..003f7bf4e2e3 100644 --- a/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h +++ b/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h @@ -11,7 +11,7 @@ #ifndef __ARCH_ARM_MACH_OMAP2_SDRAM_NUMONYX_M65KXXXXAM #define __ARCH_ARM_MACH_OMAP2_SDRAM_NUMONYX_M65KXXXXAM -#include <plat/sdrc.h> +#include "sdrc.h" /* Numonyx M65KXXXXAM */ static struct omap_sdrc_params m65kxxxxam_sdrc_params[] = { diff --git a/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h b/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h index 0e518a72831f..8dc3de5ebb5b 100644 --- a/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h +++ b/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h @@ -14,7 +14,7 @@ #ifndef ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6 #define ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6 -#include <plat/sdrc.h> +#include "sdrc.h" /* Qimonda HYB18M512160AF-6 */ static struct omap_sdrc_params hyb18m512160af6_sdrc_params[] = { diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c index e3d345f46409..94d4082f87ed 100644 --- a/arch/arm/mach-omap2/sdrc.c +++ b/arch/arm/mach-omap2/sdrc.c @@ -23,11 +23,10 @@ #include <linux/clk.h> #include <linux/io.h> -#include "common.h" -#include <plat/clock.h> -#include <plat/sram.h> +#include "../plat-omap/sram.h" -#include <plat/sdrc.h> +#include "common.h" +#include "clock.h" #include "sdrc.h" static struct omap_sdrc_params *sdrc_init_params_cs0, *sdrc_init_params_cs1; @@ -160,19 +159,3 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0, sdrc_write_reg(l, SDRC_POWER); omap2_sms_save_context(); } - -void omap2_sms_write_rot_control(u32 val, unsigned ctx) -{ - sms_write_reg(val, SMS_ROT_CONTROL(ctx)); -} - -void omap2_sms_write_rot_size(u32 val, unsigned ctx) -{ - sms_write_reg(val, SMS_ROT_SIZE(ctx)); -} - -void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx) -{ - sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx)); -} - diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h index b3f83799e6cf..69c4b329452e 100644 --- a/arch/arm/mach-omap2/sdrc.h +++ b/arch/arm/mach-omap2/sdrc.h @@ -2,12 +2,14 @@ #define __ARCH_ARM_MACH_OMAP2_SDRC_H /* - * OMAP2 SDRC register definitions + * OMAP2/3 SDRC/SMS macros and prototypes * - * Copyright (C) 2007 Texas Instruments, Inc. - * Copyright (C) 2007 Nokia Corporation + * Copyright (C) 2007-2008, 2012 Texas Instruments, Inc. + * Copyright (C) 2007-2008 Nokia Corporation * - * Written by Paul Walmsley + * Paul Walmsley + * Tony Lindgren + * Richard Woodruff * * 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 @@ -15,8 +17,6 @@ */ #undef DEBUG -#include <plat/sdrc.h> - #ifndef __ASSEMBLER__ #include <linux/io.h> @@ -50,6 +50,58 @@ static inline u32 sms_read_reg(u16 reg) { return __raw_readl(OMAP_SMS_REGADDR(reg)); } + + +/** + * struct omap_sdrc_params - SDRC parameters for a given SDRC clock rate + * @rate: SDRC clock rate (in Hz) + * @actim_ctrla: Value to program to SDRC_ACTIM_CTRLA for this rate + * @actim_ctrlb: Value to program to SDRC_ACTIM_CTRLB for this rate + * @rfr_ctrl: Value to program to SDRC_RFR_CTRL for this rate + * @mr: Value to program to SDRC_MR for this rate + * + * This structure holds a pre-computed set of register values for the + * SDRC for a given SDRC clock rate and SDRAM chip. These are + * intended to be pre-computed and specified in an array in the board-*.c + * files. The structure is keyed off the 'rate' field. + */ +struct omap_sdrc_params { + unsigned long rate; + u32 actim_ctrla; + u32 actim_ctrlb; + u32 rfr_ctrl; + u32 mr; +}; + +#ifdef CONFIG_SOC_HAS_OMAP2_SDRC +void omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0, + struct omap_sdrc_params *sdrc_cs1); +#else +static inline void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0, + struct omap_sdrc_params *sdrc_cs1) {}; +#endif + +int omap2_sdrc_get_params(unsigned long r, + struct omap_sdrc_params **sdrc_cs0, + struct omap_sdrc_params **sdrc_cs1); +void omap2_sms_save_context(void); +void omap2_sms_restore_context(void); + +struct memory_timings { + u32 m_type; /* ddr = 1, sdr = 0 */ + u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */ + u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */ + u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */ + u32 base_cs; /* base chip select to use for calculations */ +}; + +extern void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode); +struct omap_sdrc_params *rx51_get_sdram_timings(void); + +u32 omap2xxx_sdrc_dll_is_unlocked(void); +u32 omap2xxx_sdrc_reprogram(u32 level, u32 force); + + #else #define OMAP242X_SDRC_REGADDR(reg) \ OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE + (reg)) @@ -57,6 +109,7 @@ static inline u32 sms_read_reg(u16 reg) OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE + (reg)) #define OMAP34XX_SDRC_REGADDR(reg) \ OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE + (reg)) + #endif /* __ASSEMBLER__ */ /* Minimum frequency that the SDRC DLL can lock at */ @@ -74,4 +127,85 @@ static inline u32 sms_read_reg(u16 reg) */ #define SDRC_MPURATE_LOOPS 96 +/* SDRC register offsets - read/write with sdrc_{read,write}_reg() */ + +#define SDRC_SYSCONFIG 0x010 +#define SDRC_CS_CFG 0x040 +#define SDRC_SHARING 0x044 +#define SDRC_ERR_TYPE 0x04C +#define SDRC_DLLA_CTRL 0x060 +#define SDRC_DLLA_STATUS 0x064 +#define SDRC_DLLB_CTRL 0x068 +#define SDRC_DLLB_STATUS 0x06C +#define SDRC_POWER 0x070 +#define SDRC_MCFG_0 0x080 +#define SDRC_MR_0 0x084 +#define SDRC_EMR2_0 0x08c +#define SDRC_ACTIM_CTRL_A_0 0x09c +#define SDRC_ACTIM_CTRL_B_0 0x0a0 +#define SDRC_RFR_CTRL_0 0x0a4 +#define SDRC_MANUAL_0 0x0a8 +#define SDRC_MCFG_1 0x0B0 +#define SDRC_MR_1 0x0B4 +#define SDRC_EMR2_1 0x0BC +#define SDRC_ACTIM_CTRL_A_1 0x0C4 +#define SDRC_ACTIM_CTRL_B_1 0x0C8 +#define SDRC_RFR_CTRL_1 0x0D4 +#define SDRC_MANUAL_1 0x0D8 + +#define SDRC_POWER_AUTOCOUNT_SHIFT 8 +#define SDRC_POWER_AUTOCOUNT_MASK (0xffff << SDRC_POWER_AUTOCOUNT_SHIFT) +#define SDRC_POWER_CLKCTRL_SHIFT 4 +#define SDRC_POWER_CLKCTRL_MASK (0x3 << SDRC_POWER_CLKCTRL_SHIFT) +#define SDRC_SELF_REFRESH_ON_AUTOCOUNT (0x2 << SDRC_POWER_CLKCTRL_SHIFT) + +/* + * These values represent the number of memory clock cycles between + * autorefresh initiation. They assume 1 refresh per 64 ms (JEDEC), 8192 + * rows per device, and include a subtraction of a 50 cycle window in the + * event that the autorefresh command is delayed due to other SDRC activity. + * The '| 1' sets the ARE field to send one autorefresh when the autorefresh + * counter reaches 0. + * + * These represent optimal values for common parts, it won't work for all. + * As long as you scale down, most parameters are still work, they just + * become sub-optimal. The RFR value goes in the opposite direction. If you + * don't adjust it down as your clock period increases the refresh interval + * will not be met. Setting all parameters for complete worst case may work, + * but may cut memory performance by 2x. Due to errata the DLLs need to be + * unlocked and their value needs run time calibration. A dynamic call is + * need for that as no single right value exists acorss production samples. + * + * Only the FULL speed values are given. Current code is such that rate + * changes must be made at DPLLoutx2. The actual value adjustment for low + * frequency operation will be handled by omap_set_performance() + * + * By having the boot loader boot up in the fastest L4 speed available likely + * will result in something which you can switch between. + */ +#define SDRC_RFR_CTRL_165MHz (0x00044c00 | 1) +#define SDRC_RFR_CTRL_133MHz (0x0003de00 | 1) +#define SDRC_RFR_CTRL_100MHz (0x0002da01 | 1) +#define SDRC_RFR_CTRL_110MHz (0x0002da01 | 1) /* Need to calc */ +#define SDRC_RFR_CTRL_BYPASS (0x00005000 | 1) /* Need to calc */ + + +/* + * SMS register access + */ + +#define OMAP242X_SMS_REGADDR(reg) \ + (void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE + reg) +#define OMAP243X_SMS_REGADDR(reg) \ + (void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE + reg) +#define OMAP343X_SMS_REGADDR(reg) \ + (void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE + reg) + +/* SMS register offsets - read/write with sms_{read,write}_reg() */ + +#define SMS_SYSCONFIG 0x010 +/* REVISIT: fill in other SMS registers here */ + + + #endif diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c index 73e55e485329..3b8bfdf848d5 100644 --- a/arch/arm/mach-omap2/sdrc2xxx.c +++ b/arch/arm/mach-omap2/sdrc2xxx.c @@ -24,9 +24,7 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/clock.h> -#include <plat/sram.h> -#include <plat/sdrc.h> +#include "../plat-omap/sram.h" #include "soc.h" #include "iomap.h" diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 0405c8190803..12363f313f08 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -28,13 +28,14 @@ #include <linux/console.h> #include <plat/omap-serial.h> -#include "common.h" -#include <plat/dma.h> -#include <plat/omap_hwmod.h> -#include <plat/omap_device.h> -#include <plat/omap-pm.h> +#include <plat-omap/dma-omap.h> #include <plat/serial.h> +#include "common.h" +#include "omap_hwmod.h" +#include "omap_device.h" +#include "omap-pm.h" +#include "soc.h" #include "prm2xxx_3xxx.h" #include "pm.h" #include "cm2xxx_3xxx.h" diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S index 506987979c1c..75afe11207ff 100644 --- a/arch/arm/mach-omap2/sleep34xx.S +++ b/arch/arm/mach-omap2/sleep34xx.S @@ -26,7 +26,7 @@ #include <asm/assembler.h> -#include <plat/sram.h> +#include "../plat-omap/sram.h" #include "omap34xx.h" #include "iomap.h" diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h index fc9b96daf851..070096496e20 100644 --- a/arch/arm/mach-omap2/soc.h +++ b/arch/arm/mach-omap2/soc.h @@ -1,7 +1,473 @@ -#include <plat/cpu.h> +/* + * OMAP cpu type detection + * + * Copyright (C) 2004, 2008 Nokia Corporation + * + * Copyright (C) 2009-11 Texas Instruments. + * + * Written by Tony Lindgren <tony.lindgren@nokia.com> + * + * Added OMAP4/5 specific defines - Santosh Shilimkar<santosh.shilimkar@ti.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + #include "omap24xx.h" #include "omap34xx.h" #include "omap44xx.h" #include "ti81xx.h" #include "am33xx.h" #include "omap54xx.h" + +#ifndef __ASSEMBLY__ + +#include <linux/bitops.h> + +/* + * Test if multicore OMAP support is needed + */ +#undef MULTI_OMAP2 +#undef OMAP_NAME + +#ifdef CONFIG_SOC_OMAP2420 +# ifdef OMAP_NAME +# undef MULTI_OMAP2 +# define MULTI_OMAP2 +# else +# define OMAP_NAME omap2420 +# endif +#endif +#ifdef CONFIG_SOC_OMAP2430 +# ifdef OMAP_NAME +# undef MULTI_OMAP2 +# define MULTI_OMAP2 +# else +# define OMAP_NAME omap2430 +# endif +#endif +#ifdef CONFIG_ARCH_OMAP3 +# ifdef OMAP_NAME +# undef MULTI_OMAP2 +# define MULTI_OMAP2 +# else +# define OMAP_NAME omap3 +# endif +#endif +#ifdef CONFIG_ARCH_OMAP4 +# ifdef OMAP_NAME +# undef MULTI_OMAP2 +# define MULTI_OMAP2 +# else +# define OMAP_NAME omap4 +# endif +#endif + +#ifdef CONFIG_SOC_OMAP5 +# ifdef OMAP_NAME +# undef MULTI_OMAP2 +# define MULTI_OMAP2 +# else +# define OMAP_NAME omap5 +# endif +#endif + +#ifdef CONFIG_SOC_AM33XX +# ifdef OMAP_NAME +# undef MULTI_OMAP2 +# define MULTI_OMAP2 +# else +# define OMAP_NAME am33xx +# endif +#endif + +/* + * Omap device type i.e. EMU/HS/TST/GP/BAD + */ +#define OMAP2_DEVICE_TYPE_TEST 0 +#define OMAP2_DEVICE_TYPE_EMU 1 +#define OMAP2_DEVICE_TYPE_SEC 2 +#define OMAP2_DEVICE_TYPE_GP 3 +#define OMAP2_DEVICE_TYPE_BAD 4 + +int omap_type(void); + +/* + * omap_rev bits: + * CPU id bits (0730, 1510, 1710, 2422...) [31:16] + * CPU revision (See _REV_ defined in cpu.h) [15:08] + * CPU class bits (15xx, 16xx, 24xx, 34xx...) [07:00] + */ +unsigned int omap_rev(void); + +/* + * Get the CPU revision for OMAP devices + */ +#define GET_OMAP_REVISION() ((omap_rev() >> 8) & 0xff) + +/* + * Macros to group OMAP into cpu classes. + * These can be used in most places. + * cpu_is_omap24xx(): True for OMAP2420, OMAP2422, OMAP2423, OMAP2430 + * cpu_is_omap242x(): True for OMAP2420, OMAP2422, OMAP2423 + * cpu_is_omap243x(): True for OMAP2430 + * cpu_is_omap343x(): True for OMAP3430 + * cpu_is_omap443x(): True for OMAP4430 + * cpu_is_omap446x(): True for OMAP4460 + * cpu_is_omap447x(): True for OMAP4470 + * soc_is_omap543x(): True for OMAP5430, OMAP5432 + */ +#define GET_OMAP_CLASS (omap_rev() & 0xff) + +#define IS_OMAP_CLASS(class, id) \ +static inline int is_omap ##class (void) \ +{ \ + return (GET_OMAP_CLASS == (id)) ? 1 : 0; \ +} + +#define GET_AM_CLASS ((omap_rev() >> 24) & 0xff) + +#define IS_AM_CLASS(class, id) \ +static inline int is_am ##class (void) \ +{ \ + return (GET_AM_CLASS == (id)) ? 1 : 0; \ +} + +#define GET_TI_CLASS ((omap_rev() >> 24) & 0xff) + +#define IS_TI_CLASS(class, id) \ +static inline int is_ti ##class (void) \ +{ \ + return (GET_TI_CLASS == (id)) ? 1 : 0; \ +} + +#define GET_OMAP_SUBCLASS ((omap_rev() >> 20) & 0x0fff) + +#define IS_OMAP_SUBCLASS(subclass, id) \ +static inline int is_omap ##subclass (void) \ +{ \ + return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0; \ +} + +#define IS_TI_SUBCLASS(subclass, id) \ +static inline int is_ti ##subclass (void) \ +{ \ + return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0; \ +} + +#define IS_AM_SUBCLASS(subclass, id) \ +static inline int is_am ##subclass (void) \ +{ \ + return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0; \ +} + +IS_OMAP_CLASS(24xx, 0x24) +IS_OMAP_CLASS(34xx, 0x34) +IS_OMAP_CLASS(44xx, 0x44) +IS_AM_CLASS(35xx, 0x35) +IS_OMAP_CLASS(54xx, 0x54) +IS_AM_CLASS(33xx, 0x33) + +IS_TI_CLASS(81xx, 0x81) + +IS_OMAP_SUBCLASS(242x, 0x242) +IS_OMAP_SUBCLASS(243x, 0x243) +IS_OMAP_SUBCLASS(343x, 0x343) +IS_OMAP_SUBCLASS(363x, 0x363) +IS_OMAP_SUBCLASS(443x, 0x443) +IS_OMAP_SUBCLASS(446x, 0x446) +IS_OMAP_SUBCLASS(447x, 0x447) +IS_OMAP_SUBCLASS(543x, 0x543) + +IS_TI_SUBCLASS(816x, 0x816) +IS_TI_SUBCLASS(814x, 0x814) +IS_AM_SUBCLASS(335x, 0x335) + +#define cpu_is_omap24xx() 0 +#define cpu_is_omap242x() 0 +#define cpu_is_omap243x() 0 +#define cpu_is_omap34xx() 0 +#define cpu_is_omap343x() 0 +#define cpu_is_ti81xx() 0 +#define cpu_is_ti816x() 0 +#define cpu_is_ti814x() 0 +#define soc_is_am35xx() 0 +#define soc_is_am33xx() 0 +#define soc_is_am335x() 0 +#define cpu_is_omap44xx() 0 +#define cpu_is_omap443x() 0 +#define cpu_is_omap446x() 0 +#define cpu_is_omap447x() 0 +#define soc_is_omap54xx() 0 +#define soc_is_omap543x() 0 + +#if defined(MULTI_OMAP2) +# if defined(CONFIG_ARCH_OMAP2) +# undef cpu_is_omap24xx +# define cpu_is_omap24xx() is_omap24xx() +# endif +# if defined (CONFIG_SOC_OMAP2420) +# undef cpu_is_omap242x +# define cpu_is_omap242x() is_omap242x() +# endif +# if defined (CONFIG_SOC_OMAP2430) +# undef cpu_is_omap243x +# define cpu_is_omap243x() is_omap243x() +# endif +# if defined(CONFIG_ARCH_OMAP3) +# undef cpu_is_omap34xx +# undef cpu_is_omap343x +# define cpu_is_omap34xx() is_omap34xx() +# define cpu_is_omap343x() is_omap343x() +# endif +#else +# if defined(CONFIG_ARCH_OMAP2) +# undef cpu_is_omap24xx +# define cpu_is_omap24xx() 1 +# endif +# if defined(CONFIG_SOC_OMAP2420) +# undef cpu_is_omap242x +# define cpu_is_omap242x() 1 +# endif +# if defined(CONFIG_SOC_OMAP2430) +# undef cpu_is_omap243x +# define cpu_is_omap243x() 1 +# endif +# if defined(CONFIG_ARCH_OMAP3) +# undef cpu_is_omap34xx +# define cpu_is_omap34xx() 1 +# endif +# if defined(CONFIG_SOC_OMAP3430) +# undef cpu_is_omap343x +# define cpu_is_omap343x() 1 +# endif +#endif + +/* + * Macros to detect individual cpu types. + * These are only rarely needed. + * cpu_is_omap2420(): True for OMAP2420 + * cpu_is_omap2422(): True for OMAP2422 + * cpu_is_omap2423(): True for OMAP2423 + * cpu_is_omap2430(): True for OMAP2430 + * cpu_is_omap3430(): True for OMAP3430 + */ +#define GET_OMAP_TYPE ((omap_rev() >> 16) & 0xffff) + +#define IS_OMAP_TYPE(type, id) \ +static inline int is_omap ##type (void) \ +{ \ + return (GET_OMAP_TYPE == (id)) ? 1 : 0; \ +} + +IS_OMAP_TYPE(2420, 0x2420) +IS_OMAP_TYPE(2422, 0x2422) +IS_OMAP_TYPE(2423, 0x2423) +IS_OMAP_TYPE(2430, 0x2430) +IS_OMAP_TYPE(3430, 0x3430) + +#define cpu_is_omap2420() 0 +#define cpu_is_omap2422() 0 +#define cpu_is_omap2423() 0 +#define cpu_is_omap2430() 0 +#define cpu_is_omap3430() 0 +#define cpu_is_omap3630() 0 +#define soc_is_omap5430() 0 + +/* These are needed for the common code */ +#ifdef CONFIG_ARCH_OMAP2PLUS +#define cpu_is_omap7xx() 0 +#define cpu_is_omap15xx() 0 +#define cpu_is_omap16xx() 0 +#define cpu_is_omap1510() 0 +#define cpu_is_omap1610() 0 +#define cpu_is_omap1611() 0 +#define cpu_is_omap1621() 0 +#define cpu_is_omap1710() 0 +#define cpu_class_is_omap1() 0 +#define cpu_class_is_omap2() 1 +#endif + +#if defined(CONFIG_ARCH_OMAP2) +# undef cpu_is_omap2420 +# undef cpu_is_omap2422 +# undef cpu_is_omap2423 +# undef cpu_is_omap2430 +# define cpu_is_omap2420() is_omap2420() +# define cpu_is_omap2422() is_omap2422() +# define cpu_is_omap2423() is_omap2423() +# define cpu_is_omap2430() is_omap2430() +#endif + +#if defined(CONFIG_ARCH_OMAP3) +# undef cpu_is_omap3430 +# undef cpu_is_ti81xx +# undef cpu_is_ti816x +# undef cpu_is_ti814x +# undef soc_is_am35xx +# define cpu_is_omap3430() is_omap3430() +# undef cpu_is_omap3630 +# define cpu_is_omap3630() is_omap363x() +# define cpu_is_ti81xx() is_ti81xx() +# define cpu_is_ti816x() is_ti816x() +# define cpu_is_ti814x() is_ti814x() +# define soc_is_am35xx() is_am35xx() +#endif + +# if defined(CONFIG_SOC_AM33XX) +# undef soc_is_am33xx +# undef soc_is_am335x +# define soc_is_am33xx() is_am33xx() +# define soc_is_am335x() is_am335x() +#endif + +# if defined(CONFIG_ARCH_OMAP4) +# undef cpu_is_omap44xx +# undef cpu_is_omap443x +# undef cpu_is_omap446x +# undef cpu_is_omap447x +# define cpu_is_omap44xx() is_omap44xx() +# define cpu_is_omap443x() is_omap443x() +# define cpu_is_omap446x() is_omap446x() +# define cpu_is_omap447x() is_omap447x() +# endif + +# if defined(CONFIG_SOC_OMAP5) +# undef soc_is_omap54xx +# undef soc_is_omap543x +# define soc_is_omap54xx() is_omap54xx() +# define soc_is_omap543x() is_omap543x() +#endif + +/* Various silicon revisions for omap2 */ +#define OMAP242X_CLASS 0x24200024 +#define OMAP2420_REV_ES1_0 OMAP242X_CLASS +#define OMAP2420_REV_ES2_0 (OMAP242X_CLASS | (0x1 << 8)) + +#define OMAP243X_CLASS 0x24300024 +#define OMAP2430_REV_ES1_0 OMAP243X_CLASS + +#define OMAP343X_CLASS 0x34300034 +#define OMAP3430_REV_ES1_0 OMAP343X_CLASS +#define OMAP3430_REV_ES2_0 (OMAP343X_CLASS | (0x1 << 8)) +#define OMAP3430_REV_ES2_1 (OMAP343X_CLASS | (0x2 << 8)) +#define OMAP3430_REV_ES3_0 (OMAP343X_CLASS | (0x3 << 8)) +#define OMAP3430_REV_ES3_1 (OMAP343X_CLASS | (0x4 << 8)) +#define OMAP3430_REV_ES3_1_2 (OMAP343X_CLASS | (0x5 << 8)) + +#define OMAP363X_CLASS 0x36300034 +#define OMAP3630_REV_ES1_0 OMAP363X_CLASS +#define OMAP3630_REV_ES1_1 (OMAP363X_CLASS | (0x1 << 8)) +#define OMAP3630_REV_ES1_2 (OMAP363X_CLASS | (0x2 << 8)) + +#define TI816X_CLASS 0x81600034 +#define TI8168_REV_ES1_0 TI816X_CLASS +#define TI8168_REV_ES1_1 (TI816X_CLASS | (0x1 << 8)) + +#define TI814X_CLASS 0x81400034 +#define TI8148_REV_ES1_0 TI814X_CLASS +#define TI8148_REV_ES2_0 (TI814X_CLASS | (0x1 << 8)) +#define TI8148_REV_ES2_1 (TI814X_CLASS | (0x2 << 8)) + +#define AM35XX_CLASS 0x35170034 +#define AM35XX_REV_ES1_0 AM35XX_CLASS +#define AM35XX_REV_ES1_1 (AM35XX_CLASS | (0x1 << 8)) + +#define AM335X_CLASS 0x33500033 +#define AM335X_REV_ES1_0 AM335X_CLASS + +#define OMAP443X_CLASS 0x44300044 +#define OMAP4430_REV_ES1_0 (OMAP443X_CLASS | (0x10 << 8)) +#define OMAP4430_REV_ES2_0 (OMAP443X_CLASS | (0x20 << 8)) +#define OMAP4430_REV_ES2_1 (OMAP443X_CLASS | (0x21 << 8)) +#define OMAP4430_REV_ES2_2 (OMAP443X_CLASS | (0x22 << 8)) +#define OMAP4430_REV_ES2_3 (OMAP443X_CLASS | (0x23 << 8)) + +#define OMAP446X_CLASS 0x44600044 +#define OMAP4460_REV_ES1_0 (OMAP446X_CLASS | (0x10 << 8)) +#define OMAP4460_REV_ES1_1 (OMAP446X_CLASS | (0x11 << 8)) + +#define OMAP447X_CLASS 0x44700044 +#define OMAP4470_REV_ES1_0 (OMAP447X_CLASS | (0x10 << 8)) + +#define OMAP54XX_CLASS 0x54000054 +#define OMAP5430_REV_ES1_0 (OMAP54XX_CLASS | (0x30 << 16) | (0x10 << 8)) +#define OMAP5432_REV_ES1_0 (OMAP54XX_CLASS | (0x32 << 16) | (0x10 << 8)) + +void omap2xxx_check_revision(void); +void omap3xxx_check_revision(void); +void omap4xxx_check_revision(void); +void omap5xxx_check_revision(void); +void omap3xxx_check_features(void); +void ti81xx_check_features(void); +void omap4xxx_check_features(void); + +/* + * Runtime detection of OMAP3 features + * + * OMAP3_HAS_IO_CHAIN_CTRL: Some later members of the OMAP3 chip + * family have OS-level control over the I/O chain clock. This is + * to avoid a window during which wakeups could potentially be lost + * during powerdomain transitions. If this bit is set, it + * indicates that the chip does support OS-level control of this + * feature. + */ +extern u32 omap_features; + +#define OMAP3_HAS_L2CACHE BIT(0) +#define OMAP3_HAS_IVA BIT(1) +#define OMAP3_HAS_SGX BIT(2) +#define OMAP3_HAS_NEON BIT(3) +#define OMAP3_HAS_ISP BIT(4) +#define OMAP3_HAS_192MHZ_CLK BIT(5) +#define OMAP3_HAS_IO_WAKEUP BIT(6) +#define OMAP3_HAS_SDRC BIT(7) +#define OMAP3_HAS_IO_CHAIN_CTRL BIT(8) +#define OMAP4_HAS_MPU_1GHZ BIT(9) +#define OMAP4_HAS_MPU_1_2GHZ BIT(10) +#define OMAP4_HAS_MPU_1_5GHZ BIT(11) + + +#define OMAP3_HAS_FEATURE(feat,flag) \ +static inline unsigned int omap3_has_ ##feat(void) \ +{ \ + return omap_features & OMAP3_HAS_ ##flag; \ +} \ + +OMAP3_HAS_FEATURE(l2cache, L2CACHE) +OMAP3_HAS_FEATURE(sgx, SGX) +OMAP3_HAS_FEATURE(iva, IVA) +OMAP3_HAS_FEATURE(neon, NEON) +OMAP3_HAS_FEATURE(isp, ISP) +OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK) +OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP) +OMAP3_HAS_FEATURE(sdrc, SDRC) +OMAP3_HAS_FEATURE(io_chain_ctrl, IO_CHAIN_CTRL) + +/* + * Runtime detection of OMAP4 features + */ +#define OMAP4_HAS_FEATURE(feat, flag) \ +static inline unsigned int omap4_has_ ##feat(void) \ +{ \ + return omap_features & OMAP4_HAS_ ##flag; \ +} \ + +OMAP4_HAS_FEATURE(mpu_1ghz, MPU_1GHZ) +OMAP4_HAS_FEATURE(mpu_1_2ghz, MPU_1_2GHZ) +OMAP4_HAS_FEATURE(mpu_1_5ghz, MPU_1_5GHZ) + +#endif /* __ASSEMBLY__ */ + diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index f8217a5a4a26..b0e77a407047 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -23,8 +23,8 @@ #include <linux/slab.h> #include <linux/io.h> -#include <plat/omap_device.h> - +#include "soc.h" +#include "omap_device.h" #include "voltage.h" #include "control.h" #include "pm.h" diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 44f9aa7ec0c0..45598ac819be 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -43,10 +43,10 @@ #include <asm/sched_clock.h> #include <asm/arch_timer.h> -#include <plat/omap_hwmod.h> -#include <plat/omap_device.h> +#include "omap_hwmod.h" +#include "omap_device.h" #include <plat/dmtimer.h> -#include <plat/omap-pm.h> +#include "omap-pm.h" #include "soc.h" #include "common.h" diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index 635e109f5ad3..1a0739d397f3 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -26,7 +26,6 @@ #include <linux/regulator/machine.h> #include <linux/regulator/fixed.h> -#include <plat/i2c.h> #include <plat/usb.h> #include "soc.h" diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c index 3c434498e12e..4fe67129643d 100644 --- a/arch/arm/mach-omap2/usb-host.c +++ b/arch/arm/mach-omap2/usb-host.c @@ -26,7 +26,8 @@ #include <asm/io.h> #include <plat/usb.h> -#include <plat/omap_device.h> +#include "soc.h" +#include "omap_device.h" #include "mux.h" diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index 51da21cb78f1..07f385a2900c 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -26,10 +26,9 @@ #include <linux/usb/musb.h> #include <plat/usb.h> -#include <plat/omap_device.h> - -#include "am35xx.h" +#include "omap_device.h" +#include "soc.h" #include "mux.h" static struct musb_hdrc_config musb_config = { diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index 805bea6edf17..6064425ed47b 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -18,7 +18,7 @@ #include <linux/usb/musb.h> -#include <plat/gpmc.h> +#include "gpmc.h" #include "mux.h" diff --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c index b2f1c67043a2..f6b6c37ac3f4 100644 --- a/arch/arm/mach-omap2/wd_timer.c +++ b/arch/arm/mach-omap2/wd_timer.c @@ -11,7 +11,7 @@ #include <linux/io.h> #include <linux/err.h> -#include <plat/omap_hwmod.h> +#include "omap_hwmod.h" #include "wd_timer.h" #include "common.h" diff --git a/arch/arm/mach-omap2/wd_timer.h b/arch/arm/mach-omap2/wd_timer.h index f6bbba73b535..a78f81034a9f 100644 --- a/arch/arm/mach-omap2/wd_timer.h +++ b/arch/arm/mach-omap2/wd_timer.h @@ -10,7 +10,7 @@ #ifndef __ARCH_ARM_MACH_OMAP2_WD_TIMER_H #define __ARCH_ARM_MACH_OMAP2_WD_TIMER_H -#include <plat/omap_hwmod.h> +#include "omap_hwmod.h" extern int omap2_wd_timer_disable(struct omap_hwmod *oh); extern int omap2_wd_timer_reset(struct omap_hwmod *oh); |