diff options
Diffstat (limited to 'arch/arm/mach-omap2')
34 files changed, 820 insertions, 833 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index b068b7fe99ef..62bb352c2d37 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -229,7 +229,6 @@ obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o obj-$(CONFIG_MACH_OMAP3530_LV_SOM) += board-omap3logic.o obj-$(CONFIG_MACH_OMAP3_TORPEDO) += board-omap3logic.o -obj-$(CONFIG_MACH_ENCORE) += board-omap3encore.o obj-$(CONFIG_MACH_OVERO) += board-overo.o obj-$(CONFIG_MACH_OMAP3EVM) += board-omap3evm.o obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o @@ -255,8 +254,6 @@ obj-$(CONFIG_MACH_TOUCHBOOK) += board-omap3touchbook.o obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o -obj-$(CONFIG_MACH_PCM049) += board-omap4pcm049.o - obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o obj-$(CONFIG_MACH_CRANEBOARD) += board-am3517crane.o diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index cb0596b631cf..244d8a5aa54b 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -38,7 +38,7 @@ #include "gpmc-smc91x.h" #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-data.h> #include "mux.h" #include "hsmmc.h" @@ -108,24 +108,13 @@ static struct platform_device *sdp2430_devices[] __initdata = { #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 #define SDP2430_LCD_PANEL_ENABLE_GPIO 154 -static int sdp2430_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 1); - gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 1); - - return 0; -} - -static void sdp2430_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 0); - gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 0); -} - static struct panel_generic_dpi_data sdp2430_panel_data = { .name = "nec_nl2432dr22-11b", - .platform_enable = sdp2430_panel_enable_lcd, - .platform_disable = sdp2430_panel_disable_lcd, + .num_gpios = 2, + .gpios = { + SDP2430_LCD_PANEL_ENABLE_GPIO, + SDP2430_LCD_PANEL_BACKLIGHT_GPIO, + }, }; static struct omap_dss_device sdp2430_lcd_device = { @@ -146,26 +135,6 @@ static struct omap_dss_board_info sdp2430_dss_data = { .default_device = &sdp2430_lcd_device, }; -static void __init sdp2430_display_init(void) -{ - int r; - - static struct gpio gpios[] __initdata = { - { SDP2430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW, - "LCD reset" }, - { SDP2430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW, - "LCD Backlight" }, - }; - - r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); - if (r) { - pr_err("Cannot request LCD GPIOs, error %d\n", r); - return; - } - - omap_display_init(&sdp2430_dss_data); -} - #if IS_ENABLED(CONFIG_SMC91X) static struct omap_smc91x_platform_data board_smc91x_data = { @@ -273,7 +242,7 @@ static void __init omap_2430sdp_init(void) gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW, "Secondary LCD backlight"); - sdp2430_display_init(); + omap_display_init(&sdp2430_dss_data); } MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board") diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 7eb9651dd0f7..23b004afa3f8 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -35,7 +35,7 @@ #include "common.h" #include <linux/omap-dma.h> #include <video/omapdss.h> -#include <video/omap-panel-tfp410.h> +#include <video/omap-panel-data.h> #include "gpmc.h" #include "gpmc-smc91x.h" @@ -108,53 +108,38 @@ static struct twl4030_keypad_data sdp3430_kp_data = { #define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8 #define SDP3430_LCD_PANEL_ENABLE_GPIO 5 -static struct gpio sdp3430_dss_gpios[] __initdata = { - {SDP3430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW, "LCD reset" }, - {SDP3430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW, "LCD Backlight"}, -}; - static void __init sdp3430_display_init(void) { int r; - r = gpio_request_array(sdp3430_dss_gpios, - ARRAY_SIZE(sdp3430_dss_gpios)); + /* + * the backlight GPIO doesn't directly go to the panel, it enables + * an internal circuit on 3430sdp to create the signal V_BKL_28V, + * this is connected to LED+ pin of the sharp panel. This GPIO + * is left enabled in the board file, and not passed to the panel + * as platform_data. + */ + r = gpio_request_one(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, + GPIOF_OUT_INIT_HIGH, "LCD Backlight"); if (r) - printk(KERN_ERR "failed to get LCD control GPIOs\n"); - -} + pr_err("failed to get LCD Backlight GPIO\n"); -static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - gpio_direction_output(SDP3430_LCD_PANEL_ENABLE_GPIO, 1); - gpio_direction_output(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, 1); - - return 0; -} - -static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - gpio_direction_output(SDP3430_LCD_PANEL_ENABLE_GPIO, 0); - gpio_direction_output(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, 0); -} - -static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev) -{ } +static struct panel_sharp_ls037v7dw01_data sdp3430_lcd_data = { + .resb_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO, + .ini_gpio = -1, + .mo_gpio = -1, + .lr_gpio = -1, + .ud_gpio = -1, +}; static struct omap_dss_device sdp3430_lcd_device = { .name = "lcd", .driver_name = "sharp_ls_panel", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 16, - .platform_enable = sdp3430_panel_enable_lcd, - .platform_disable = sdp3430_panel_disable_lcd, + .data = &sdp3430_lcd_data, }; static struct tfp410_platform_data dvi_panel = { @@ -175,8 +160,6 @@ static struct omap_dss_device sdp3430_tv_device = { .driver_name = "venc", .type = OMAP_DISPLAY_TYPE_VENC, .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, - .platform_enable = sdp3430_panel_enable_tv, - .platform_disable = sdp3430_panel_disable_tv, }; diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 306df0b40935..56a9a4f855c7 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -291,6 +291,10 @@ static struct platform_device sdp4430_leds_pwm = { }, }; +/* Dummy regulator for pwm-backlight driver */ +static struct regulator_consumer_supply backlight_supply = + REGULATOR_SUPPLY("enable", "pwm-backlight"); + static struct platform_pwm_backlight_data sdp4430_backlight_data = { .max_brightness = 127, .dft_brightness = 127, @@ -718,6 +722,8 @@ static void __init omap_4430sdp_init(void) omap4_i2c_init(); omap_sfh7741prox_init(); + regulator_register_always_on(0, "backlight-enable", + &backlight_supply, 1, 0); platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices)); omap_serial_init(); omap_sdrc_init(NULL, NULL); diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 191f9762ba63..d63f14b534b5 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -35,8 +35,7 @@ #include "common.h" #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> -#include <video/omap-panel-tfp410.h> +#include <video/omap-panel-data.h> #include "am35xx-emac.h" #include "mux.h" @@ -121,63 +120,14 @@ static int __init am3517_evm_i2c_init(void) return 0; } -static int lcd_enabled; -static int dvi_enabled; - -#if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \ - defined(CONFIG_PANEL_SHARP_LQ043T1DG01_MODULE) -static struct gpio am3517_evm_dss_gpios[] __initdata = { - /* GPIO 182 = LCD Backlight Power */ - { LCD_PANEL_BKLIGHT_PWR, GPIOF_OUT_INIT_HIGH, "lcd_backlight_pwr" }, - /* GPIO 181 = LCD Panel PWM */ - { LCD_PANEL_PWM, GPIOF_OUT_INIT_HIGH, "lcd bl enable" }, - /* GPIO 176 = LCD Panel Power enable pin */ - { LCD_PANEL_PWR, GPIOF_OUT_INIT_HIGH, "dvi enable" }, -}; - -static void __init am3517_evm_display_init(void) -{ - int r; - - omap_mux_init_gpio(LCD_PANEL_PWR, OMAP_PIN_INPUT_PULLUP); - omap_mux_init_gpio(LCD_PANEL_BKLIGHT_PWR, OMAP_PIN_INPUT_PULLDOWN); - omap_mux_init_gpio(LCD_PANEL_PWM, OMAP_PIN_INPUT_PULLDOWN); - - r = gpio_request_array(am3517_evm_dss_gpios, - ARRAY_SIZE(am3517_evm_dss_gpios)); - if (r) { - printk(KERN_ERR "failed to get DSS panel control GPIOs\n"); - return; - } - - printk(KERN_INFO "Display initialized successfully\n"); -} -#else -static void __init am3517_evm_display_init(void) {} -#endif - -static int am3517_evm_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - if (dvi_enabled) { - printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); - return -EINVAL; - } - gpio_set_value(LCD_PANEL_PWR, 1); - lcd_enabled = 1; - - return 0; -} - -static void am3517_evm_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - gpio_set_value(LCD_PANEL_PWR, 0); - lcd_enabled = 0; -} - static struct panel_generic_dpi_data lcd_panel = { .name = "sharp_lq", - .platform_enable = am3517_evm_panel_enable_lcd, - .platform_disable = am3517_evm_panel_disable_lcd, + .num_gpios = 3, + .gpios = { + LCD_PANEL_PWR, + LCD_PANEL_BKLIGHT_PWR, + LCD_PANEL_PWM, + }, }; static struct omap_dss_device am3517_evm_lcd_device = { @@ -188,22 +138,11 @@ static struct omap_dss_device am3517_evm_lcd_device = { .phy.dpi.data_lines = 16, }; -static int am3517_evm_panel_enable_tv(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void am3517_evm_panel_disable_tv(struct omap_dss_device *dssdev) -{ -} - static struct omap_dss_device am3517_evm_tv_device = { .type = OMAP_DISPLAY_TYPE_VENC, .name = "tv", .driver_name = "venc", .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, - .platform_enable = am3517_evm_panel_enable_tv, - .platform_disable = am3517_evm_panel_disable_tv, }; static struct tfp410_platform_data dvi_panel = { @@ -366,8 +305,6 @@ static void __init am3517_evm_init(void) usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data)); usbhs_init(&usbhs_bdata); am3517_evm_hecc_init(&am3517_evm_hecc_pdata); - /* DSS */ - am3517_evm_display_init(); /* RTC - S35390A */ am3517_evm_rtc_init(); diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 7fda3f5f8a7f..ee6218c74807 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -41,8 +41,7 @@ #include <linux/platform_data/mtd-nand-omap2.h> #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> -#include <video/omap-panel-tfp410.h> +#include <video/omap-panel-data.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include "common.h" @@ -191,45 +190,12 @@ static inline void cm_t35_init_nand(void) {} #define CM_T35_LCD_BL_GPIO 58 #define CM_T35_DVI_EN_GPIO 54 -static int lcd_enabled; -static int dvi_enabled; - -static int cm_t35_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - if (dvi_enabled) { - printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); - return -EINVAL; - } - - gpio_set_value(CM_T35_LCD_EN_GPIO, 1); - gpio_set_value(CM_T35_LCD_BL_GPIO, 1); - - lcd_enabled = 1; - - return 0; -} - -static void cm_t35_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - lcd_enabled = 0; - - gpio_set_value(CM_T35_LCD_BL_GPIO, 0); - gpio_set_value(CM_T35_LCD_EN_GPIO, 0); -} - -static int cm_t35_panel_enable_tv(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void cm_t35_panel_disable_tv(struct omap_dss_device *dssdev) -{ -} - static struct panel_generic_dpi_data lcd_panel = { .name = "toppoly_tdo35s", - .platform_enable = cm_t35_panel_enable_lcd, - .platform_disable = cm_t35_panel_disable_lcd, + .num_gpios = 1, + .gpios = { + CM_T35_LCD_BL_GPIO, + }, }; static struct omap_dss_device cm_t35_lcd_device = { @@ -258,8 +224,6 @@ static struct omap_dss_device cm_t35_tv_device = { .driver_name = "venc", .type = OMAP_DISPLAY_TYPE_VENC, .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, - .platform_enable = cm_t35_panel_enable_tv, - .platform_disable = cm_t35_panel_disable_tv, }; static struct omap_dss_device *cm_t35_dss_devices[] = { @@ -293,11 +257,6 @@ static struct spi_board_info cm_t35_lcd_spi_board_info[] __initdata = { }, }; -static struct gpio cm_t35_dss_gpios[] __initdata = { - { CM_T35_LCD_EN_GPIO, GPIOF_OUT_INIT_LOW, "lcd enable" }, - { CM_T35_LCD_BL_GPIO, GPIOF_OUT_INIT_LOW, "lcd bl enable" }, -}; - static void __init cm_t35_init_display(void) { int err; @@ -305,23 +264,21 @@ static void __init cm_t35_init_display(void) spi_register_board_info(cm_t35_lcd_spi_board_info, ARRAY_SIZE(cm_t35_lcd_spi_board_info)); - err = gpio_request_array(cm_t35_dss_gpios, - ARRAY_SIZE(cm_t35_dss_gpios)); + + err = gpio_request_one(CM_T35_LCD_EN_GPIO, GPIOF_OUT_INIT_LOW, + "lcd bl enable"); if (err) { - pr_err("CM-T35: failed to request DSS control GPIOs\n"); + pr_err("CM-T35: failed to request LCD EN GPIO\n"); return; } - gpio_export(CM_T35_LCD_EN_GPIO, 0); - gpio_export(CM_T35_LCD_BL_GPIO, 0); - msleep(50); gpio_set_value(CM_T35_LCD_EN_GPIO, 1); err = omap_display_init(&cm_t35_dss_data); if (err) { pr_err("CM-T35: failed to register DSS device\n"); - gpio_free_array(cm_t35_dss_gpios, ARRAY_SIZE(cm_t35_dss_gpios)); + gpio_free(CM_T35_LCD_EN_GPIO); } } diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 42fbf1ef12a9..576420544178 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -43,8 +43,7 @@ #include "gpmc.h" #include <linux/platform_data/mtd-nand-omap2.h> #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> -#include <video/omap-panel-tfp410.h> +#include <video/omap-panel-data.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/input/matrix_keypad.h> @@ -104,19 +103,6 @@ static struct omap2_hsmmc_info mmc[] = { {} /* Terminator */ }; -static int devkit8000_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - if (gpio_is_valid(dssdev->reset_gpio)) - gpio_set_value_cansleep(dssdev->reset_gpio, 1); - return 0; -} - -static void devkit8000_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - if (gpio_is_valid(dssdev->reset_gpio)) - gpio_set_value_cansleep(dssdev->reset_gpio, 0); -} - static struct regulator_consumer_supply devkit8000_vmmc1_supply[] = { REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"), }; @@ -128,8 +114,7 @@ static struct regulator_consumer_supply devkit8000_vio_supply[] = { static struct panel_generic_dpi_data lcd_panel = { .name = "innolux_at070tn83", - .platform_enable = devkit8000_panel_enable_lcd, - .platform_disable = devkit8000_panel_disable_lcd, + /* gpios filled in code */ }; static struct omap_dss_device devkit8000_lcd_device = { @@ -211,8 +196,6 @@ static struct gpio_led gpio_leds[]; static int devkit8000_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { - int ret; - /* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0].gpio_cd = gpio + 0; omap_hsmmc_late_init(mmc); @@ -221,13 +204,8 @@ static int devkit8000_twl_gpio_setup(struct device *dev, gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; /* TWL4030_GPIO_MAX + 0 is "LCD_PWREN" (out, active high) */ - devkit8000_lcd_device.reset_gpio = gpio + TWL4030_GPIO_MAX + 0; - ret = gpio_request_one(devkit8000_lcd_device.reset_gpio, - GPIOF_OUT_INIT_LOW, "LCD_PWREN"); - if (ret < 0) { - devkit8000_lcd_device.reset_gpio = -EINVAL; - printk(KERN_ERR "Failed to request GPIO for LCD_PWRN\n"); - } + lcd_panel.num_gpios = 1; + lcd_panel.gpios[0] = gpio + TWL4030_GPIO_MAX + 0; /* gpio + 7 is "DVI_PD" (out, active low) */ dvi_panel.power_down_gpio = gpio + 7; diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 5b4ec51c385f..69c0acf5aa63 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -34,7 +34,7 @@ #include <asm/mach/map.h> #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-data.h> #include "common.h" #include "mux.h" diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 95ccec0eeab9..b54562d1235e 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -31,7 +31,7 @@ #include <asm/mach/arch.h> #include <video/omapdss.h> -#include <video/omap-panel-tfp410.h> +#include <video/omap-panel-data.h> #include <linux/platform_data/mtd-onenand-omap2.h> #include "common.h" diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index b12fe966a7b9..d0d17bc58d9b 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -41,7 +41,7 @@ #include "gpmc-smsc911x.h" #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-data.h> #include "board-flash.h" #include "mux.h" @@ -181,34 +181,13 @@ static inline void __init ldp_init_smsc911x(void) /* LCD */ -static int ldp_backlight_gpio; -static int ldp_lcd_enable_gpio; - #define LCD_PANEL_RESET_GPIO 55 #define LCD_PANEL_QVGA_GPIO 56 -static int ldp_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - if (gpio_is_valid(ldp_lcd_enable_gpio)) - gpio_direction_output(ldp_lcd_enable_gpio, 1); - if (gpio_is_valid(ldp_backlight_gpio)) - gpio_direction_output(ldp_backlight_gpio, 1); - - return 0; -} - -static void ldp_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - if (gpio_is_valid(ldp_lcd_enable_gpio)) - gpio_direction_output(ldp_lcd_enable_gpio, 0); - if (gpio_is_valid(ldp_backlight_gpio)) - gpio_direction_output(ldp_backlight_gpio, 0); -} - static struct panel_generic_dpi_data ldp_panel_data = { .name = "nec_nl2432dr22-11b", - .platform_enable = ldp_panel_enable_lcd, - .platform_disable = ldp_panel_disable_lcd, + .num_gpios = 4, + /* gpios filled in code */ }; static struct omap_dss_device ldp_lcd_device = { @@ -231,41 +210,19 @@ static struct omap_dss_board_info ldp_dss_data = { static void __init ldp_display_init(void) { - int r; - - static struct gpio gpios[] __initdata = { - {LCD_PANEL_RESET_GPIO, GPIOF_OUT_INIT_HIGH, "LCD RESET"}, - {LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "LCD QVGA"}, - }; - - r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); - if (r) { - pr_err("Cannot request LCD GPIOs, error %d\n", r); - return; - } + ldp_panel_data.gpios[2] = LCD_PANEL_RESET_GPIO; + ldp_panel_data.gpios[3] = LCD_PANEL_QVGA_GPIO; omap_display_init(&ldp_dss_data); } static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { - int r; - - struct gpio gpios[] = { - {gpio + 7 , GPIOF_OUT_INIT_LOW, "LCD ENABLE"}, - {gpio + 15, GPIOF_OUT_INIT_LOW, "LCD BACKLIGHT"}, - }; - - r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); - if (r) { - pr_err("Cannot request LCD GPIOs, error %d\n", r); - ldp_backlight_gpio = -EINVAL; - ldp_lcd_enable_gpio = -EINVAL; - return r; - } - - ldp_backlight_gpio = gpio + 15; - ldp_lcd_enable_gpio = gpio + 7; + ldp_panel_data.gpios[0] = gpio + 7; + ldp_panel_data.gpio_invert[0] = true; + + ldp_panel_data.gpios[1] = gpio + 15; + ldp_panel_data.gpio_invert[1] = true; return 0; } diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 6955a428f534..6de78605c0af 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -44,7 +44,7 @@ #include <asm/mach/flash.h> #include <video/omapdss.h> -#include <video/omap-panel-tfp410.h> +#include <video/omap-panel-data.h> #include <linux/platform_data/mtd-nand-omap2.h> #include "common.h" diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 2de92facc8a3..f76d0de7b406 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -51,7 +51,7 @@ #include "common.h" #include <linux/platform_data/spi-omap2-mcspi.h> #include <video/omapdss.h> -#include <video/omap-panel-tfp410.h> +#include <video/omap-panel-data.h> #include "soc.h" #include "mux.h" @@ -155,61 +155,43 @@ static inline void __init omap3evm_init_smsc911x(void) { return; } #define OMAP3EVM_LCD_PANEL_LR 2 #define OMAP3EVM_LCD_PANEL_UD 3 #define OMAP3EVM_LCD_PANEL_INI 152 -#define OMAP3EVM_LCD_PANEL_ENVDD 153 #define OMAP3EVM_LCD_PANEL_QVGA 154 #define OMAP3EVM_LCD_PANEL_RESB 155 + +#define OMAP3EVM_LCD_PANEL_ENVDD 153 #define OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO 210 + +/* + * OMAP3EVM DVI control signals + */ #define OMAP3EVM_DVI_PANEL_EN_GPIO 199 -static struct gpio omap3_evm_dss_gpios[] __initdata = { - { OMAP3EVM_LCD_PANEL_RESB, GPIOF_OUT_INIT_HIGH, "lcd_panel_resb" }, - { OMAP3EVM_LCD_PANEL_INI, GPIOF_OUT_INIT_HIGH, "lcd_panel_ini" }, - { OMAP3EVM_LCD_PANEL_QVGA, GPIOF_OUT_INIT_LOW, "lcd_panel_qvga" }, - { OMAP3EVM_LCD_PANEL_LR, GPIOF_OUT_INIT_HIGH, "lcd_panel_lr" }, - { OMAP3EVM_LCD_PANEL_UD, GPIOF_OUT_INIT_HIGH, "lcd_panel_ud" }, - { OMAP3EVM_LCD_PANEL_ENVDD, GPIOF_OUT_INIT_LOW, "lcd_panel_envdd" }, +static struct panel_sharp_ls037v7dw01_data omap3_evm_lcd_data = { + .resb_gpio = OMAP3EVM_LCD_PANEL_RESB, + .ini_gpio = OMAP3EVM_LCD_PANEL_INI, + .mo_gpio = OMAP3EVM_LCD_PANEL_QVGA, + .lr_gpio = OMAP3EVM_LCD_PANEL_LR, + .ud_gpio = OMAP3EVM_LCD_PANEL_UD, }; -static int lcd_enabled; -static int dvi_enabled; - static void __init omap3_evm_display_init(void) { int r; - r = gpio_request_array(omap3_evm_dss_gpios, - ARRAY_SIZE(omap3_evm_dss_gpios)); + r = gpio_request_one(OMAP3EVM_LCD_PANEL_ENVDD, GPIOF_OUT_INIT_LOW, + "lcd_panel_envdd"); if (r) - printk(KERN_ERR "failed to get lcd_panel_* gpios\n"); -} + pr_err("failed to get lcd_panel_envdd GPIO\n"); -static int omap3_evm_enable_lcd(struct omap_dss_device *dssdev) -{ - if (dvi_enabled) { - printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); - return -EINVAL; - } - gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 0); + r = gpio_request_one(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, + GPIOF_OUT_INIT_LOW, "lcd_panel_bklight"); + if (r) + pr_err("failed to get lcd_panel_bklight GPIO\n"); if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0); else gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1); - - lcd_enabled = 1; - return 0; -} - -static void omap3_evm_disable_lcd(struct omap_dss_device *dssdev) -{ - gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 1); - - if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) - gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1); - else - gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0); - - lcd_enabled = 0; } static struct omap_dss_device omap3_evm_lcd_device = { @@ -217,26 +199,14 @@ static struct omap_dss_device omap3_evm_lcd_device = { .driver_name = "sharp_ls_panel", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 18, - .platform_enable = omap3_evm_enable_lcd, - .platform_disable = omap3_evm_disable_lcd, + .data = &omap3_evm_lcd_data, }; -static int omap3_evm_enable_tv(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void omap3_evm_disable_tv(struct omap_dss_device *dssdev) -{ -} - static struct omap_dss_device omap3_evm_tv_device = { .name = "tv", .driver_name = "venc", .type = OMAP_DISPLAY_TYPE_VENC, .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, - .platform_enable = omap3_evm_enable_tv, - .platform_disable = omap3_evm_disable_tv, }; static struct tfp410_platform_data dvi_panel = { diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 1004d2aaa68f..28133d5b4fed 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -44,6 +44,7 @@ #include "common.h" #include <video/omapdss.h> +#include <video/omap-panel-data.h> #include <linux/platform_data/mtd-nand-omap2.h> #include "mux.h" @@ -230,12 +231,16 @@ static struct twl4030_keypad_data pandora_kp_data = { .rep = 1, }; +static struct panel_tpo_td043_data lcd_data = { + .nreset_gpio = 157, +}; + static struct omap_dss_device pandora_lcd_device = { .name = "lcd", .driver_name = "tpo_td043mtea1_panel", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 24, - .reset_gpio = 157, + .data = &lcd_data, }; static struct omap_dss_device pandora_tv_device = { diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index bf0956489899..d37e6b187ae4 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -44,8 +44,7 @@ #include "gpmc.h" #include <linux/platform_data/mtd-nand-omap2.h> #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> -#include <video/omap-panel-tfp410.h> +#include <video/omap-panel-data.h> #include <linux/platform_data/spi-omap2-mcspi.h> @@ -95,15 +94,6 @@ static void __init omap3_stalker_display_init(void) return; } -static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void omap3_stalker_disable_tv(struct omap_dss_device *dssdev) -{ -} - static struct omap_dss_device omap3_stalker_tv_device = { .name = "tv", .driver_name = "venc", @@ -113,8 +103,6 @@ static struct omap_dss_device omap3_stalker_tv_device = { #elif defined(CONFIG_OMAP2_VENC_OUT_TYPE_COMPOSITE) .u.venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE, #endif - .platform_enable = omap3_stalker_enable_tv, - .platform_disable = omap3_stalker_disable_tv, }; static struct tfp410_platform_data dvi_panel = { diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index ab79a4422bcc..4ca6b680aa72 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -47,8 +47,7 @@ #include <asm/mach/map.h> #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> -#include <video/omap-panel-tfp410.h> +#include <video/omap-panel-data.h> #include "common.h" #include "mux.h" @@ -146,28 +145,9 @@ static inline void __init overo_init_smsc911x(void) { return; } #endif /* DSS */ -static int lcd_enabled; -static int dvi_enabled; - #define OVERO_GPIO_LCD_EN 144 #define OVERO_GPIO_LCD_BL 145 -static struct gpio overo_dss_gpios[] __initdata = { - { OVERO_GPIO_LCD_EN, GPIOF_OUT_INIT_HIGH, "OVERO_GPIO_LCD_EN" }, - { OVERO_GPIO_LCD_BL, GPIOF_OUT_INIT_HIGH, "OVERO_GPIO_LCD_BL" }, -}; - -static void __init overo_display_init(void) -{ - if (gpio_request_array(overo_dss_gpios, ARRAY_SIZE(overo_dss_gpios))) { - printk(KERN_ERR "could not obtain DSS control GPIOs\n"); - return; - } - - gpio_export(OVERO_GPIO_LCD_EN, 0); - gpio_export(OVERO_GPIO_LCD_BL, 0); -} - static struct tfp410_platform_data dvi_panel = { .i2c_bus_num = 3, .power_down_gpio = -1, @@ -188,30 +168,13 @@ static struct omap_dss_device overo_tv_device = { .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, }; -static int overo_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - if (dvi_enabled) { - printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); - return -EINVAL; - } - - gpio_set_value(OVERO_GPIO_LCD_EN, 1); - gpio_set_value(OVERO_GPIO_LCD_BL, 1); - lcd_enabled = 1; - return 0; -} - -static void overo_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - gpio_set_value(OVERO_GPIO_LCD_EN, 0); - gpio_set_value(OVERO_GPIO_LCD_BL, 0); - lcd_enabled = 0; -} - static struct panel_generic_dpi_data lcd43_panel = { .name = "samsung_lte430wq_f0c", - .platform_enable = overo_panel_enable_lcd, - .platform_disable = overo_panel_disable_lcd, + .num_gpios = 2, + .gpios = { + OVERO_GPIO_LCD_EN, + OVERO_GPIO_LCD_BL + }, }; static struct omap_dss_device overo_lcd43_device = { @@ -224,13 +187,20 @@ static struct omap_dss_device overo_lcd43_device = { #if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \ defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE) +static struct panel_generic_dpi_data lcd35_panel = { + .num_gpios = 2, + .gpios = { + OVERO_GPIO_LCD_EN, + OVERO_GPIO_LCD_BL + }, +}; + static struct omap_dss_device overo_lcd35_device = { .type = OMAP_DISPLAY_TYPE_DPI, .name = "lcd35", .driver_name = "lgphilips_lb035q02_panel", .phy.dpi.data_lines = 24, - .platform_enable = overo_panel_enable_lcd, - .platform_disable = overo_panel_disable_lcd, + .data = &lcd35_panel, }; #endif @@ -509,7 +479,6 @@ static void __init overo_init(void) usbhs_init(&usbhs_bdata); overo_spi_init(); overo_init_smsc911x(); - overo_display_init(); overo_init_led(); overo_init_keys(); omap_twl4030_audio_init("overo", NULL); diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 3a077df6b8df..1a884670a6c4 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -547,12 +547,16 @@ static struct regulator_consumer_supply rx51_vio_supplies[] = { REGULATOR_SUPPLY("DVDD", "2-0019"), /* Si4713 IO supply */ REGULATOR_SUPPLY("vio", "2-0063"), + /* lis3lv02d */ + REGULATOR_SUPPLY("Vdd_IO", "3-001d"), }; static struct regulator_consumer_supply rx51_vaux1_consumers[] = { REGULATOR_SUPPLY("vdds_sdi", "omapdss"), /* Si4713 supply */ REGULATOR_SUPPLY("vdd", "2-0063"), + /* lis3lv02d */ + REGULATOR_SUPPLY("Vdd", "3-001d"), }; static struct regulator_init_data rx51_vaux1 = { diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c index eb667261df08..bd74f9f6063b 100644 --- a/arch/arm/mach-omap2/board-rx51-video.c +++ b/arch/arm/mach-omap2/board-rx51-video.c @@ -16,6 +16,8 @@ #include <linux/mm.h> #include <asm/mach-types.h> #include <video/omapdss.h> +#include <video/omap-panel-data.h> + #include <linux/platform_data/spi-omap2-mcspi.h> #include "soc.h" @@ -27,25 +29,16 @@ #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) -static int rx51_lcd_enable(struct omap_dss_device *dssdev) -{ - gpio_set_value(dssdev->reset_gpio, 1); - return 0; -} - -static void rx51_lcd_disable(struct omap_dss_device *dssdev) -{ - gpio_set_value(dssdev->reset_gpio, 0); -} +static struct panel_acx565akm_data lcd_data = { + .reset_gpio = RX51_LCD_RESET_GPIO, +}; static struct omap_dss_device rx51_lcd_device = { .name = "lcd", .driver_name = "panel-acx565akm", .type = OMAP_DISPLAY_TYPE_SDI, .phy.sdi.datapairs = 2, - .reset_gpio = RX51_LCD_RESET_GPIO, - .platform_enable = rx51_lcd_enable, - .platform_disable = rx51_lcd_disable, + .data = &lcd_data, }; static struct omap_dss_device rx51_tv_device = { @@ -76,13 +69,8 @@ static int __init rx51_video_init(void) return 0; } - if (gpio_request_one(RX51_LCD_RESET_GPIO, GPIOF_OUT_INIT_HIGH, - "LCD ACX565AKM reset")) { - pr_err("%s failed to get LCD Reset GPIO\n", __func__); - return 0; - } - omap_display_init(&rx51_dss_board_info); + return 0; } diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c index 8cef477d6b00..c2a079cb76fc 100644 --- a/arch/arm/mach-omap2/board-zoom-display.c +++ b/arch/arm/mach-omap2/board-zoom-display.c @@ -12,12 +12,12 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/gpio.h> -#include <linux/i2c/twl.h> #include <linux/spi/spi.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <video/omapdss.h> -#include "board-zoom.h" +#include <video/omap-panel-data.h> +#include "board-zoom.h" #include "soc.h" #include "common.h" @@ -25,92 +25,17 @@ #define LCD_PANEL_RESET_GPIO_PILOT 55 #define LCD_PANEL_QVGA_GPIO 56 -static struct gpio zoom_lcd_gpios[] __initdata = { - { -EINVAL, GPIOF_OUT_INIT_HIGH, "lcd reset" }, - { LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "lcd qvga" }, +static struct panel_nec_nl8048_data zoom_lcd_data = { + /* res_gpio filled in code */ + .qvga_gpio = LCD_PANEL_QVGA_GPIO, }; -static void __init zoom_lcd_panel_init(void) -{ - zoom_lcd_gpios[0].gpio = (omap_rev() > OMAP3430_REV_ES3_0) ? - LCD_PANEL_RESET_GPIO_PROD : - LCD_PANEL_RESET_GPIO_PILOT; - - if (gpio_request_array(zoom_lcd_gpios, ARRAY_SIZE(zoom_lcd_gpios))) - pr_err("%s: Failed to get LCD GPIOs.\n", __func__); -} - -static int zoom_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void zoom_panel_disable_lcd(struct omap_dss_device *dssdev) -{ -} - -/* Register offsets in TWL4030_MODULE_INTBR */ -#define TWL_INTBR_PMBR1 0xD -#define TWL_INTBR_GPBR1 0xC - -/* Register offsets in TWL_MODULE_PWM */ -#define TWL_LED_PWMON 0x3 -#define TWL_LED_PWMOFF 0x4 - -static int zoom_set_bl_intensity(struct omap_dss_device *dssdev, int level) -{ -#ifdef CONFIG_TWL4030_CORE - unsigned char c; - u8 mux_pwm, enb_pwm; - - if (level > 100) - return -1; - - twl_i2c_read_u8(TWL4030_MODULE_INTBR, &mux_pwm, TWL_INTBR_PMBR1); - twl_i2c_read_u8(TWL4030_MODULE_INTBR, &enb_pwm, TWL_INTBR_GPBR1); - - if (level == 0) { - /* disable pwm1 output and clock */ - enb_pwm = enb_pwm & 0xF5; - /* change pwm1 pin to gpio pin */ - mux_pwm = mux_pwm & 0xCF; - twl_i2c_write_u8(TWL4030_MODULE_INTBR, - enb_pwm, TWL_INTBR_GPBR1); - twl_i2c_write_u8(TWL4030_MODULE_INTBR, - mux_pwm, TWL_INTBR_PMBR1); - return 0; - } - - if (!((enb_pwm & 0xA) && (mux_pwm & 0x30))) { - /* change gpio pin to pwm1 pin */ - mux_pwm = mux_pwm | 0x30; - /* enable pwm1 output and clock*/ - enb_pwm = enb_pwm | 0x0A; - twl_i2c_write_u8(TWL4030_MODULE_INTBR, - mux_pwm, TWL_INTBR_PMBR1); - twl_i2c_write_u8(TWL4030_MODULE_INTBR, - enb_pwm, TWL_INTBR_GPBR1); - } - - c = ((50 * (100 - level)) / 100) + 1; - twl_i2c_write_u8(TWL_MODULE_PWM, 0x7F, TWL_LED_PWMOFF); - twl_i2c_write_u8(TWL_MODULE_PWM, c, TWL_LED_PWMON); -#else - pr_warn("Backlight not enabled\n"); -#endif - - return 0; -} - static struct omap_dss_device zoom_lcd_device = { .name = "lcd", .driver_name = "NEC_8048_panel", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 24, - .platform_enable = zoom_panel_enable_lcd, - .platform_disable = zoom_panel_disable_lcd, - .max_backlight_level = 100, - .set_backlight = zoom_set_bl_intensity, + .data = &zoom_lcd_data, }; static struct omap_dss_device *zoom_dss_devices[] = { @@ -123,6 +48,13 @@ static struct omap_dss_board_info zoom_dss_data = { .default_device = &zoom_lcd_device, }; +static void __init zoom_lcd_panel_init(void) +{ + zoom_lcd_data.res_gpio = (omap_rev() > OMAP3430_REV_ES3_0) ? + LCD_PANEL_RESET_GPIO_PROD : + LCD_PANEL_RESET_GPIO_PILOT; +} + static struct omap2_mcspi_device_config dss_lcd_mcspi_config = { .turbo_mode = 1, }; diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index cdc0c1021863..a90375d5b2b6 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c @@ -22,6 +22,9 @@ #include <linux/platform_data/gpio-omap.h> #include <linux/platform_data/omap-twl4030.h> #include <linux/usb/phy.h> +#include <linux/pwm.h> +#include <linux/leds_pwm.h> +#include <linux/pwm_backlight.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -193,6 +196,53 @@ static struct platform_device omap_vwlan_device = { }, }; +static struct pwm_lookup zoom_pwm_lookup[] = { + PWM_LOOKUP("twl-pwm", 0, "leds_pwm", "zoom::keypad"), + PWM_LOOKUP("twl-pwm", 1, "pwm-backlight", "backlight"), +}; + +static struct led_pwm zoom_pwm_leds[] = { + { + .name = "zoom::keypad", + .max_brightness = 127, + .pwm_period_ns = 7812500, + }, +}; + +static struct led_pwm_platform_data zoom_pwm_data = { + .num_leds = ARRAY_SIZE(zoom_pwm_leds), + .leds = zoom_pwm_leds, +}; + +static struct platform_device zoom_leds_pwm = { + .name = "leds_pwm", + .id = -1, + .dev = { + .platform_data = &zoom_pwm_data, + }, +}; + +static struct platform_pwm_backlight_data zoom_backlight_data = { + .pwm_id = 1, + .max_brightness = 127, + .dft_brightness = 127, + .pwm_period_ns = 7812500, +}; + +static struct platform_device zoom_backlight_pwm = { + .name = "pwm-backlight", + .id = -1, + .dev = { + .platform_data = &zoom_backlight_data, + }, +}; + +static struct platform_device *zoom_devices[] __initdata = { + &omap_vwlan_device, + &zoom_leds_pwm, + &zoom_backlight_pwm, +}; + static struct wl12xx_platform_data omap_zoom_wlan_data __initdata = { .board_ref_clock = WL12XX_REFCLOCK_26, /* 26 MHz */ }; @@ -301,7 +351,8 @@ void __init zoom_peripherals_init(void) omap_hsmmc_init(mmc); omap_i2c_init(); - platform_device_register(&omap_vwlan_device); + pwm_add_table(zoom_pwm_lookup, ARRAY_SIZE(zoom_pwm_lookup)); + platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices)); usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); usb_musb_init(NULL); enable_board_wakeup_source(); diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c index 3d58f335f173..0c6834ae1fc4 100644 --- a/arch/arm/mach-omap2/cclock44xx_data.c +++ b/arch/arm/mach-omap2/cclock44xx_data.c @@ -52,6 +52,13 @@ */ #define OMAP4_DPLL_ABE_DEFFREQ 98304000 +/* + * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section + * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred + * locked frequency for the USB DPLL is 960MHz. + */ +#define OMAP4_DPLL_USB_DEFFREQ 960000000 + /* Root clocks */ DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0); @@ -1011,6 +1018,10 @@ DEFINE_CLK_OMAP_MUX(hsmmc2_fclk, "l3_init_clkdm", hsmmc1_fclk_sel, OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK, hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops); +DEFINE_CLK_GATE(ocp2scp_usb_phy_phy_48m, "func_48m_fclk", &func_48m_fclk, 0x0, + OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, + OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, 0x0, NULL); + DEFINE_CLK_GATE(sha2md5_fck, "l3_div_ck", &l3_div_ck, 0x0, OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); @@ -1538,6 +1549,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "per_mcbsp4_gfclk", &per_mcbsp4_gfclk, CK_443X), CLK(NULL, "hsmmc1_fclk", &hsmmc1_fclk, CK_443X), CLK(NULL, "hsmmc2_fclk", &hsmmc2_fclk, CK_443X), + CLK(NULL, "ocp2scp_usb_phy_phy_48m", &ocp2scp_usb_phy_phy_48m, CK_443X), CLK(NULL, "sha2md5_fck", &sha2md5_fck, CK_443X), CLK(NULL, "slimbus1_fclk_1", &slimbus1_fclk_1, CK_443X), CLK(NULL, "slimbus1_fclk_0", &slimbus1_fclk_0, CK_443X), @@ -1705,5 +1717,13 @@ int __init omap4xxx_clk_init(void) if (rc) pr_err("%s: failed to configure ABE DPLL!\n", __func__); + /* + * Lock USB DPLL on OMAP4 devices so that the L3INIT power + * domain can transition to retention state when not in use. + */ + rc = clk_set_rate(&dpll_usb_ck, OMAP4_DPLL_USB_DEFFREQ); + if (rc) + pr_err("%s: failed to configure USB DPLL!\n", __func__); + return 0; } diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index bf70e2b57ff8..272490e72ee0 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -292,5 +292,8 @@ extern void omap_reserve(void); struct omap_hwmod; extern int omap_dss_reset(struct omap_hwmod *); +/* SoC specific clock initializer */ +extern int (*omap_clk_init)(void); + #endif /* __ASSEMBLER__ */ #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */ diff --git a/arch/arm/mach-omap2/dss-common.c b/arch/arm/mach-omap2/dss-common.c index 4be5cfc81ab8..393aeefaebb0 100644 --- a/arch/arm/mach-omap2/dss-common.c +++ b/arch/arm/mach-omap2/dss-common.c @@ -27,9 +27,7 @@ #include <linux/gpio.h> #include <video/omapdss.h> -#include <video/omap-panel-tfp410.h> -#include <video/omap-panel-nokia-dsi.h> -#include <video/omap-panel-picodlp.h> +#include <video/omap-panel-data.h> #include "soc.h" #include "dss-common.h" @@ -54,7 +52,6 @@ static struct omap_dss_device omap4_panda_dvi_device = { .driver_name = "tfp410", .data = &omap4_dvi_panel, .phy.dpi.data_lines = 24, - .reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, .channel = OMAP_DSS_CHANNEL_LCD2, }; @@ -179,45 +176,12 @@ static struct picodlp_panel_data sdp4430_picodlp_pdata = { .pwrgood_gpio = 45, }; -static void sdp4430_picodlp_init(void) -{ - int r; - const struct gpio picodlp_gpios[] = { - {DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW, - "DLP POWER ON"}, - {sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN, - "DLP EMU DONE"}, - {sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW, - "DLP PWRGOOD"}, - }; - - r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios)); - if (r) - pr_err("Cannot request PicoDLP GPIOs, error %d\n", r); -} - -static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev) -{ - gpio_set_value(DISPLAY_SEL_GPIO, 0); - gpio_set_value(DLP_POWER_ON_GPIO, 1); - - return 0; -} - -static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev) -{ - gpio_set_value(DLP_POWER_ON_GPIO, 0); - gpio_set_value(DISPLAY_SEL_GPIO, 1); -} - static struct omap_dss_device sdp4430_picodlp_device = { .name = "picodlp", .driver_name = "picodlp_panel", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 24, .channel = OMAP_DSS_CHANNEL_LCD2, - .platform_enable = sdp4430_panel_enable_picodlp, - .platform_disable = sdp4430_panel_disable_picodlp, .data = &sdp4430_picodlp_pdata, }; @@ -234,17 +198,26 @@ static struct omap_dss_board_info sdp4430_dss_data = { .default_device = &sdp4430_lcd_device, }; +/* + * we select LCD2 by default (instead of Pico DLP) by setting DISPLAY_SEL_GPIO. + * Setting DLP_POWER_ON gpio enables the VDLP_2V5 VDLP_1V8 and VDLP_1V0 rails + * used by picodlp on the 4430sdp platform. Keep this gpio disabled as LCD2 is + * selected by default + */ void __init omap_4430sdp_display_init(void) { int r; - /* Enable LCD2 by default (instead of Pico DLP) */ r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH, "display_sel"); if (r) pr_err("%s: Could not get display_sel GPIO\n", __func__); - sdp4430_picodlp_init(); + r = gpio_request_one(DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW, + "DLP POWER ON"); + if (r) + pr_err("%s: Could not get DLP POWER ON GPIO\n", __func__); + omap_display_init(&sdp4430_dss_data); /* * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and @@ -264,12 +237,15 @@ void __init omap_4430sdp_display_init_of(void) { int r; - /* Enable LCD2 by default (instead of Pico DLP) */ r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH, "display_sel"); if (r) pr_err("%s: Could not get display_sel GPIO\n", __func__); - sdp4430_picodlp_init(); + r = gpio_request_one(DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW, + "DLP POWER ON"); + if (r) + pr_err("%s: Could not get DLP POWER ON GPIO\n", __func__); + omap_display_init(&sdp4430_dss_data); } diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index afc1e8c32d6c..d9c27195caf0 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -74,14 +74,6 @@ static int omap2_nand_gpmc_retime( t.cs_wr_off = gpmc_t->cs_wr_off; t.wr_cycle = gpmc_t->wr_cycle; - /* Configure GPMC */ - if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) - gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1); - else - gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0); - gpmc_cs_configure(gpmc_nand_data->cs, - GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND); - gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_WP, 0); err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t); if (err) return err; @@ -115,14 +107,18 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, struct gpmc_timings *gpmc_t) { int err = 0; + struct gpmc_settings s; struct device *dev = &gpmc_nand_device.dev; + memset(&s, 0, sizeof(struct gpmc_settings)); + gpmc_nand_device.dev.platform_data = gpmc_nand_data; err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE, (unsigned long *)&gpmc_nand_resource[0].start); if (err < 0) { - dev_err(dev, "Cannot request GPMC CS\n"); + dev_err(dev, "Cannot request GPMC CS %d, error %d\n", + gpmc_nand_data->cs, err); return err; } @@ -140,11 +136,31 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, dev_err(dev, "Unable to set gpmc timings: %d\n", err); return err; } - } - /* Enable RD PIN Monitoring Reg */ - if (gpmc_nand_data->dev_ready) { - gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1); + if (gpmc_nand_data->of_node) { + gpmc_read_settings_dt(gpmc_nand_data->of_node, &s); + } else { + s.device_nand = true; + + /* Enable RD PIN Monitoring Reg */ + if (gpmc_nand_data->dev_ready) { + s.wait_on_read = true; + s.wait_on_write = true; + } + } + + if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) + s.device_width = GPMC_DEVWIDTH_16BIT; + else + s.device_width = GPMC_DEVWIDTH_8BIT; + + err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s); + if (err < 0) + goto out_free_cs; + + err = gpmc_configure(GPMC_CONFIG_WP, 0); + if (err < 0) + goto out_free_cs; } gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs); diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 0d75889c0a6f..64b5a8346982 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -47,11 +47,23 @@ static struct platform_device gpmc_onenand_device = { .resource = &gpmc_onenand_resource, }; -static struct gpmc_timings omap2_onenand_calc_async_timings(void) +static struct gpmc_settings onenand_async = { + .device_width = GPMC_DEVWIDTH_16BIT, + .mux_add_data = GPMC_MUX_AD, +}; + +static struct gpmc_settings onenand_sync = { + .burst_read = true, + .burst_wrap = true, + .burst_len = GPMC_BURST_16, + .device_width = GPMC_DEVWIDTH_16BIT, + .mux_add_data = GPMC_MUX_AD, + .wait_pin = 0, +}; + +static void omap2_onenand_calc_async_timings(struct gpmc_timings *t) { struct gpmc_device_timings dev_t; - struct gpmc_timings t; - const int t_cer = 15; const int t_avdp = 12; const int t_aavdh = 7; @@ -64,7 +76,6 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void) memset(&dev_t, 0, sizeof(dev_t)); - dev_t.mux = true; dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000; dev_t.t_avdp_w = dev_t.t_avdp_r; dev_t.t_aavdh = t_aavdh * 1000; @@ -76,19 +87,7 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void) dev_t.t_wpl = t_wpl * 1000; dev_t.t_wph = t_wph * 1000; - gpmc_calc_timings(&t, &dev_t); - - 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); - - return gpmc_cs_set_timings(cs, t); + gpmc_calc_timings(t, &onenand_async, &dev_t); } static void omap2_onenand_set_async_mode(void __iomem *onenand_base) @@ -158,12 +157,11 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, return freq; } -static struct gpmc_timings -omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, - int freq) +static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t, + unsigned int flags, + int freq) { struct gpmc_device_timings dev_t; - struct gpmc_timings t; const int t_cer = 15; const int t_avdp = 12; const int t_cez = 20; /* max of t_cez, t_oez */ @@ -172,9 +170,9 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; int div, gpmc_clk_ns; - if (cfg->flags & ONENAND_SYNC_READ) + if (flags & ONENAND_SYNC_READ) onenand_flags = ONENAND_FLAG_SYNCREAD; - else if (cfg->flags & ONENAND_SYNC_READWRITE) + else if (flags & ONENAND_SYNC_READWRITE) onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE; switch (freq) { @@ -239,10 +237,11 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, /* Set synchronous read timings */ memset(&dev_t, 0, sizeof(dev_t)); - dev_t.mux = true; - dev_t.sync_read = true; + if (onenand_flags & ONENAND_FLAG_SYNCREAD) + onenand_sync.sync_read = true; if (onenand_flags & ONENAND_FLAG_SYNCWRITE) { - dev_t.sync_write = true; + onenand_sync.sync_write = true; + onenand_sync.burst_write = true; } else { dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000; dev_t.t_wpl = t_wpl * 1000; @@ -265,32 +264,7 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, dev_t.cyc_aavdh_oe = 1; dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period; - gpmc_calc_timings(&t, &dev_t); - - 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 | - GPMC_CONFIG1_READMULTIPLE_SUPP | - (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | - (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | - (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | - GPMC_CONFIG1_PAGE_LEN(2) | - (cpu_is_omap34xx() ? 0 : - (GPMC_CONFIG1_WAIT_READ_MON | - GPMC_CONFIG1_WAIT_PIN_SEL(0))) | - GPMC_CONFIG1_DEVICESIZE_16 | - GPMC_CONFIG1_DEVICETYPE_NOR | - GPMC_CONFIG1_MUXADDDATA); - - return gpmc_cs_set_timings(cs, t); + gpmc_calc_timings(t, &onenand_sync, &dev_t); } static int omap2_onenand_setup_async(void __iomem *onenand_base) @@ -298,11 +272,19 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base) struct gpmc_timings t; int ret; + if (gpmc_onenand_data->of_node) + gpmc_read_settings_dt(gpmc_onenand_data->of_node, + &onenand_async); + omap2_onenand_set_async_mode(onenand_base); - t = omap2_onenand_calc_async_timings(); + omap2_onenand_calc_async_timings(&t); + + ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async); + if (ret < 0) + return ret; - ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t); + ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t); if (ret < 0) return ret; @@ -322,9 +304,25 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr) set_onenand_cfg(onenand_base); } - t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq); + if (gpmc_onenand_data->of_node) { + gpmc_read_settings_dt(gpmc_onenand_data->of_node, + &onenand_sync); + } else { + /* + * FIXME: Appears to be legacy code from initial ONENAND commit. + * Unclear what boards this is for and if this can be removed. + */ + if (!cpu_is_omap34xx()) + onenand_sync.wait_on_read = true; + } - ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t); + omap2_onenand_calc_sync_timings(&t, gpmc_onenand_data->flags, freq); + + ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_sync); + if (ret < 0) + return ret; + + ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t); if (ret < 0) return ret; @@ -359,6 +357,7 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr) void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) { int err; + struct device *dev = &gpmc_onenand_device.dev; gpmc_onenand_data = _onenand_data; gpmc_onenand_data->onenand_setup = gpmc_onenand_setup; @@ -366,7 +365,7 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) if (cpu_is_omap24xx() && (gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) { - printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n"); + dev_warn(dev, "OneNAND using only SYNC_READ on 24xx\n"); gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE; gpmc_onenand_data->flags |= ONENAND_SYNC_READ; } @@ -379,7 +378,8 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE, (unsigned long *)&gpmc_onenand_resource.start); if (err < 0) { - pr_err("%s: Cannot request GPMC CS\n", __func__); + dev_err(dev, "Cannot request GPMC CS %d, error %d\n", + gpmc_onenand_data->cs, err); return; } @@ -387,7 +387,7 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) ONENAND_IO_SIZE - 1; if (platform_device_register(&gpmc_onenand_device) < 0) { - pr_err("%s: Unable to register OneNAND device\n", __func__); + dev_err(dev, "Unable to register OneNAND device\n"); gpmc_cs_free(gpmc_onenand_data->cs); return; } diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c index 11d0b756f098..61a063595e66 100644 --- a/arch/arm/mach-omap2/gpmc-smc91x.c +++ b/arch/arm/mach-omap2/gpmc-smc91x.c @@ -49,6 +49,10 @@ static struct platform_device gpmc_smc91x_device = { .resource = gpmc_smc91x_resources, }; +static struct gpmc_settings smc91x_settings = { + .device_width = GPMC_DEVWIDTH_16BIT, +}; + /* * Set the gpmc timings for smc91c96. The timings are taken * from the data sheet available at: @@ -67,18 +71,6 @@ static int smc91c96_gpmc_retime(void) const int t7 = 5; /* Figure 12.4 write */ const int t8 = 5; /* Figure 12.4 write */ const int t20 = 185; /* Figure 12.2 read and 12.4 write */ - u32 l; - - l = GPMC_CONFIG1_DEVICESIZE_16; - if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA) - l |= GPMC_CONFIG1_MUXADDDATA; - if (gpmc_cfg->flags & GPMC_READ_MON) - l |= GPMC_CONFIG1_WAIT_READ_MON; - if (gpmc_cfg->flags & GPMC_WRITE_MON) - l |= GPMC_CONFIG1_WAIT_WRITE_MON; - if (gpmc_cfg->wait_pin) - l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin); - gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l); /* * FIXME: Calculate the address and data bus muxed timings. @@ -104,7 +96,7 @@ static int smc91c96_gpmc_retime(void) dev_t.t_cez_w = t4_w * 1000; dev_t.t_wr_cycle = (t20 - t3) * 1000; - gpmc_calc_timings(&t, &dev_t); + gpmc_calc_timings(&t, &smc91x_settings, &dev_t); return gpmc_cs_set_timings(gpmc_cfg->cs, &t); } @@ -133,6 +125,18 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data) gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f; gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK); + if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA) + smc91x_settings.mux_add_data = GPMC_MUX_AD; + if (gpmc_cfg->flags & GPMC_READ_MON) + smc91x_settings.wait_on_read = true; + if (gpmc_cfg->flags & GPMC_WRITE_MON) + smc91x_settings.wait_on_write = true; + if (gpmc_cfg->wait_pin) + smc91x_settings.wait_pin = gpmc_cfg->wait_pin; + ret = gpmc_cs_program_settings(gpmc_cfg->cs, &smc91x_settings); + if (ret < 0) + goto free1; + if (gpmc_cfg->retime) { ret = gpmc_cfg->retime(); if (ret != 0) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 6de31739b45c..ed946df5ad8a 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -26,6 +26,7 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_mtd.h> #include <linux/of_device.h> #include <linux/mtd/nand.h> @@ -91,9 +92,7 @@ #define GPMC_CS_SIZE 0x30 #define GPMC_BCH_SIZE 0x10 -#define GPMC_MEM_START 0x00000000 #define GPMC_MEM_END 0x3FFFFFFF -#define BOOT_ROM_SPACE 0x100000 /* 1MB */ #define GPMC_CHUNK_SHIFT 24 /* 16 MB */ #define GPMC_SECTION_SHIFT 28 /* 128 MB */ @@ -107,6 +106,9 @@ #define GPMC_HAS_WR_ACCESS 0x1 #define GPMC_HAS_WR_DATA_MUX_BUS 0x2 +#define GPMC_HAS_MUX_AAD 0x4 + +#define GPMC_NR_WAITPINS 4 /* XXX: Only NAND irq has been considered,currently these are the only ones used */ @@ -153,6 +155,7 @@ static struct resource gpmc_cs_mem[GPMC_CS_NUM]; static DEFINE_SPINLOCK(gpmc_mem_lock); /* Define chip-selects as reserved by default until probe completes */ static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1); +static unsigned int gpmc_nr_waitpins; static struct device *gpmc_dev; static int gpmc_irq; static resource_size_t phys_base, mem_size; @@ -181,7 +184,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val) __raw_writel(val, reg_addr); } -u32 gpmc_cs_read_reg(int cs, int idx) +static u32 gpmc_cs_read_reg(int cs, int idx) { void __iomem *reg_addr; @@ -190,7 +193,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) } /* TODO: Add support for gpmc_fck to clock framework and use it */ -unsigned long gpmc_get_fclk_period(void) +static unsigned long gpmc_get_fclk_period(void) { unsigned long rate = clk_get_rate(gpmc_l3_clk); @@ -205,7 +208,7 @@ unsigned long gpmc_get_fclk_period(void) return rate; } -unsigned int gpmc_ns_to_ticks(unsigned int time_ns) +static unsigned int gpmc_ns_to_ticks(unsigned int time_ns) { unsigned long tick_ps; @@ -215,7 +218,7 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns) return (time_ns * 1000 + tick_ps - 1) / tick_ps; } -unsigned int gpmc_ps_to_ticks(unsigned int time_ps) +static unsigned int gpmc_ps_to_ticks(unsigned int time_ps) { unsigned long tick_ps; @@ -230,13 +233,6 @@ unsigned int gpmc_ticks_to_ns(unsigned int ticks) return ticks * gpmc_get_fclk_period() / 1000; } -unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) -{ - unsigned long ticks = gpmc_ns_to_ticks(time_ns); - - return ticks * gpmc_get_fclk_period() / 1000; -} - static unsigned int gpmc_ticks_to_ps(unsigned int ticks) { return ticks * gpmc_get_fclk_period(); @@ -405,11 +401,18 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) return 0; } -static void gpmc_cs_enable_mem(int cs, u32 base, u32 size) +static int gpmc_cs_enable_mem(int cs, u32 base, u32 size) { u32 l; u32 mask; + /* + * Ensure that base address is aligned on a + * boundary equal to or greater than size. + */ + if (base & (size - 1)) + return -EINVAL; + mask = (1 << GPMC_SECTION_SHIFT) - size; l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); l &= ~0x3f; @@ -418,6 +421,8 @@ static void gpmc_cs_enable_mem(int cs, u32 base, u32 size) l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8; l |= GPMC_CONFIG7_CSVALID; gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); + + return 0; } static void gpmc_cs_disable_mem(int cs) @@ -448,22 +453,14 @@ static int gpmc_cs_mem_enabled(int cs) return l & GPMC_CONFIG7_CSVALID; } -int gpmc_cs_set_reserved(int cs, int reserved) +static void gpmc_cs_set_reserved(int cs, int reserved) { - if (cs > GPMC_CS_NUM) - return -ENODEV; - gpmc_cs_map &= ~(1 << cs); gpmc_cs_map |= (reserved ? 1 : 0) << cs; - - return 0; } -int gpmc_cs_reserved(int cs) +static bool gpmc_cs_reserved(int cs) { - if (cs > GPMC_CS_NUM) - return -ENODEV; - return gpmc_cs_map & (1 << cs); } @@ -510,6 +507,39 @@ static int gpmc_cs_delete_mem(int cs) return r; } +/** + * gpmc_cs_remap - remaps a chip-select physical base address + * @cs: chip-select to remap + * @base: physical base address to re-map chip-select to + * + * Re-maps a chip-select to a new physical base address specified by + * "base". Returns 0 on success and appropriate negative error code + * on failure. + */ +static int gpmc_cs_remap(int cs, u32 base) +{ + int ret; + u32 old_base, size; + + if (cs > GPMC_CS_NUM) + return -ENODEV; + gpmc_cs_get_memconf(cs, &old_base, &size); + if (base == old_base) + return 0; + gpmc_cs_disable_mem(cs); + ret = gpmc_cs_delete_mem(cs); + if (ret < 0) + return ret; + ret = gpmc_cs_insert_mem(cs, base, size); + if (ret < 0) + return ret; + ret = gpmc_cs_enable_mem(cs, base, size); + if (ret < 0) + return ret; + + return 0; +} + int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) { struct resource *res = &gpmc_cs_mem[cs]; @@ -535,7 +565,12 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) if (r < 0) goto out; - gpmc_cs_enable_mem(cs, res->start, resource_size(res)); + r = gpmc_cs_enable_mem(cs, res->start, resource_size(res)); + if (r < 0) { + release_resource(res); + goto out; + } + *base = res->start; gpmc_cs_set_reserved(cs, 1); out: @@ -561,16 +596,14 @@ void gpmc_cs_free(int cs) EXPORT_SYMBOL(gpmc_cs_free); /** - * gpmc_cs_configure - write request to configure gpmc - * @cs: chip select number + * gpmc_configure - write request to configure gpmc * @cmd: command type * @wval: value to write * @return status of the operation */ -int gpmc_cs_configure(int cs, int cmd, int wval) +int gpmc_configure(int cmd, int wval) { - int err = 0; - u32 regval = 0; + u32 regval; switch (cmd) { case GPMC_ENABLE_IRQ: @@ -590,43 +623,14 @@ int gpmc_cs_configure(int cs, int cmd, int wval) gpmc_write_reg(GPMC_CONFIG, regval); break; - case GPMC_CONFIG_RDY_BSY: - regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); - if (wval) - regval |= WR_RD_PIN_MONITORING; - else - regval &= ~WR_RD_PIN_MONITORING; - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); - break; - - case GPMC_CONFIG_DEV_SIZE: - regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); - - /* clear 2 target bits */ - regval &= ~GPMC_CONFIG1_DEVICESIZE(3); - - /* set the proper value */ - regval |= GPMC_CONFIG1_DEVICESIZE(wval); - - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); - break; - - case GPMC_CONFIG_DEV_TYPE: - regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); - regval |= GPMC_CONFIG1_DEVICETYPE(wval); - if (wval == GPMC_DEVICETYPE_NOR) - regval |= GPMC_CONFIG1_MUXADDDATA; - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); - break; - default: - printk(KERN_ERR "gpmc_configure_cs: Not supported\n"); - err = -EINVAL; + pr_err("%s: command not supported\n", __func__); + return -EINVAL; } - return err; + return 0; } -EXPORT_SYMBOL(gpmc_cs_configure); +EXPORT_SYMBOL(gpmc_configure); void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) { @@ -781,16 +785,16 @@ static void gpmc_mem_exit(void) } -static int gpmc_mem_init(void) +static void gpmc_mem_init(void) { - int cs, rc; - unsigned long boot_rom_space = 0; + int cs; - /* never allocate the first page, to facilitate bug detection; - * even if we didn't boot from ROM. + /* + * The first 1MB of GPMC address space is typically mapped to + * the internal ROM. Never allocate the first page, to + * facilitate bug detection; even if we didn't boot from ROM. */ - boot_rom_space = BOOT_ROM_SPACE; - gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space; + gpmc_mem_root.start = SZ_1M; gpmc_mem_root.end = GPMC_MEM_END; /* Reserve all regions that has been set up by bootloader */ @@ -800,16 +804,12 @@ static int gpmc_mem_init(void) if (!gpmc_cs_mem_enabled(cs)) continue; gpmc_cs_get_memconf(cs, &base, &size); - rc = gpmc_cs_insert_mem(cs, base, size); - if (rc < 0) { - while (--cs >= 0) - if (gpmc_cs_mem_enabled(cs)) - gpmc_cs_delete_mem(cs); - return rc; + if (gpmc_cs_insert_mem(cs, base, size)) { + pr_warn("%s: disabling cs %d mapped at 0x%x-0x%x\n", + __func__, cs, base, base + size); + gpmc_cs_disable_mem(cs); } } - - return 0; } static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk) @@ -825,9 +825,9 @@ static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk) /* XXX: can the cycles be avoided ? */ static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t, - struct gpmc_device_timings *dev_t) + struct gpmc_device_timings *dev_t, + bool mux) { - bool mux = dev_t->mux; u32 temp; /* adv_rd_off */ @@ -880,9 +880,9 @@ static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t, } static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t, - struct gpmc_device_timings *dev_t) + struct gpmc_device_timings *dev_t, + bool mux) { - bool mux = dev_t->mux; u32 temp; /* adv_wr_off */ @@ -942,9 +942,9 @@ static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t, } static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t, - struct gpmc_device_timings *dev_t) + struct gpmc_device_timings *dev_t, + bool mux) { - bool mux = dev_t->mux; u32 temp; /* adv_rd_off */ @@ -982,9 +982,9 @@ static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t, } static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t, - struct gpmc_device_timings *dev_t) + struct gpmc_device_timings *dev_t, + bool mux) { - bool mux = dev_t->mux; u32 temp; /* adv_wr_off */ @@ -1054,7 +1054,8 @@ static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t, } static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t, - struct gpmc_device_timings *dev_t) + struct gpmc_device_timings *dev_t, + bool sync) { u32 temp; @@ -1068,7 +1069,7 @@ static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t, gpmc_t->cs_on + dev_t->t_ce_avd); gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp); - if (dev_t->sync_write || dev_t->sync_read) + if (sync) gpmc_calc_sync_common_timings(gpmc_t, dev_t); return 0; @@ -1103,21 +1104,29 @@ static void gpmc_convert_ps_to_ns(struct gpmc_timings *t) } int gpmc_calc_timings(struct gpmc_timings *gpmc_t, - struct gpmc_device_timings *dev_t) + struct gpmc_settings *gpmc_s, + struct gpmc_device_timings *dev_t) { + bool mux = false, sync = false; + + if (gpmc_s) { + mux = gpmc_s->mux_add_data ? true : false; + sync = (gpmc_s->sync_read || gpmc_s->sync_write); + } + memset(gpmc_t, 0, sizeof(*gpmc_t)); - gpmc_calc_common_timings(gpmc_t, dev_t); + gpmc_calc_common_timings(gpmc_t, dev_t, sync); - if (dev_t->sync_read) - gpmc_calc_sync_read_timings(gpmc_t, dev_t); + if (gpmc_s && gpmc_s->sync_read) + gpmc_calc_sync_read_timings(gpmc_t, dev_t, mux); else - gpmc_calc_async_read_timings(gpmc_t, dev_t); + gpmc_calc_async_read_timings(gpmc_t, dev_t, mux); - if (dev_t->sync_write) - gpmc_calc_sync_write_timings(gpmc_t, dev_t); + if (gpmc_s && gpmc_s->sync_write) + gpmc_calc_sync_write_timings(gpmc_t, dev_t, mux); else - gpmc_calc_async_write_timings(gpmc_t, dev_t); + gpmc_calc_async_write_timings(gpmc_t, dev_t, mux); /* TODO: remove, see function definition */ gpmc_convert_ps_to_ns(gpmc_t); @@ -1125,6 +1134,90 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t, return 0; } +/** + * gpmc_cs_program_settings - programs non-timing related settings + * @cs: GPMC chip-select to program + * @p: pointer to GPMC settings structure + * + * Programs non-timing related settings for a GPMC chip-select, such as + * bus-width, burst configuration, etc. Function should be called once + * for each chip-select that is being used and must be called before + * calling gpmc_cs_set_timings() as timing parameters in the CONFIG1 + * register will be initialised to zero by this function. Returns 0 on + * success and appropriate negative error code on failure. + */ +int gpmc_cs_program_settings(int cs, struct gpmc_settings *p) +{ + u32 config1; + + if ((!p->device_width) || (p->device_width > GPMC_DEVWIDTH_16BIT)) { + pr_err("%s: invalid width %d!", __func__, p->device_width); + return -EINVAL; + } + + /* Address-data multiplexing not supported for NAND devices */ + if (p->device_nand && p->mux_add_data) { + pr_err("%s: invalid configuration!\n", __func__); + return -EINVAL; + } + + if ((p->mux_add_data > GPMC_MUX_AD) || + ((p->mux_add_data == GPMC_MUX_AAD) && + !(gpmc_capability & GPMC_HAS_MUX_AAD))) { + pr_err("%s: invalid multiplex configuration!\n", __func__); + return -EINVAL; + } + + /* Page/burst mode supports lengths of 4, 8 and 16 bytes */ + if (p->burst_read || p->burst_write) { + switch (p->burst_len) { + case GPMC_BURST_4: + case GPMC_BURST_8: + case GPMC_BURST_16: + break; + default: + pr_err("%s: invalid page/burst-length (%d)\n", + __func__, p->burst_len); + return -EINVAL; + } + } + + if ((p->wait_on_read || p->wait_on_write) && + (p->wait_pin > gpmc_nr_waitpins)) { + pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin); + return -EINVAL; + } + + config1 = GPMC_CONFIG1_DEVICESIZE((p->device_width - 1)); + + if (p->sync_read) + config1 |= GPMC_CONFIG1_READTYPE_SYNC; + if (p->sync_write) + config1 |= GPMC_CONFIG1_WRITETYPE_SYNC; + if (p->wait_on_read) + config1 |= GPMC_CONFIG1_WAIT_READ_MON; + if (p->wait_on_write) + config1 |= GPMC_CONFIG1_WAIT_WRITE_MON; + if (p->wait_on_read || p->wait_on_write) + config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin); + if (p->device_nand) + config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND); + if (p->mux_add_data) + config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data); + if (p->burst_read) + config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP; + if (p->burst_write) + config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP; + if (p->burst_read || p->burst_write) { + config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3); + config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0; + } + + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1); + + return 0; +} + #ifdef CONFIG_OF static struct of_device_id gpmc_dt_ids[] = { { .compatible = "ti,omap2420-gpmc" }, @@ -1136,70 +1229,110 @@ static struct of_device_id gpmc_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, gpmc_dt_ids); +/** + * gpmc_read_settings_dt - read gpmc settings from device-tree + * @np: pointer to device-tree node for a gpmc child device + * @p: pointer to gpmc settings structure + * + * Reads the GPMC settings for a GPMC child device from device-tree and + * stores them in the GPMC settings structure passed. The GPMC settings + * structure is initialised to zero by this function and so any + * previously stored settings will be cleared. + */ +void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p) +{ + memset(p, 0, sizeof(struct gpmc_settings)); + + p->sync_read = of_property_read_bool(np, "gpmc,sync-read"); + p->sync_write = of_property_read_bool(np, "gpmc,sync-write"); + p->device_nand = of_property_read_bool(np, "gpmc,device-nand"); + of_property_read_u32(np, "gpmc,device-width", &p->device_width); + of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data); + + if (!of_property_read_u32(np, "gpmc,burst-length", &p->burst_len)) { + p->burst_wrap = of_property_read_bool(np, "gpmc,burst-wrap"); + p->burst_read = of_property_read_bool(np, "gpmc,burst-read"); + p->burst_write = of_property_read_bool(np, "gpmc,burst-write"); + if (!p->burst_read && !p->burst_write) + pr_warn("%s: page/burst-length set but not used!\n", + __func__); + } + + if (!of_property_read_u32(np, "gpmc,wait-pin", &p->wait_pin)) { + p->wait_on_read = of_property_read_bool(np, + "gpmc,wait-on-read"); + p->wait_on_write = of_property_read_bool(np, + "gpmc,wait-on-write"); + if (!p->wait_on_read && !p->wait_on_write) + pr_warn("%s: read/write wait monitoring not enabled!\n", + __func__); + } +} + static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, struct gpmc_timings *gpmc_t) { - u32 val; + struct gpmc_bool_timings *p; + + if (!np || !gpmc_t) + return; memset(gpmc_t, 0, sizeof(*gpmc_t)); /* minimum clock period for syncronous mode */ - if (!of_property_read_u32(np, "gpmc,sync-clk", &val)) - gpmc_t->sync_clk = val; + of_property_read_u32(np, "gpmc,sync-clk-ps", &gpmc_t->sync_clk); /* chip select timtings */ - if (!of_property_read_u32(np, "gpmc,cs-on", &val)) - gpmc_t->cs_on = val; - - if (!of_property_read_u32(np, "gpmc,cs-rd-off", &val)) - gpmc_t->cs_rd_off = val; - - if (!of_property_read_u32(np, "gpmc,cs-wr-off", &val)) - gpmc_t->cs_wr_off = val; + of_property_read_u32(np, "gpmc,cs-on-ns", &gpmc_t->cs_on); + of_property_read_u32(np, "gpmc,cs-rd-off-ns", &gpmc_t->cs_rd_off); + of_property_read_u32(np, "gpmc,cs-wr-off-ns", &gpmc_t->cs_wr_off); /* ADV signal timings */ - if (!of_property_read_u32(np, "gpmc,adv-on", &val)) - gpmc_t->adv_on = val; - - if (!of_property_read_u32(np, "gpmc,adv-rd-off", &val)) - gpmc_t->adv_rd_off = val; - - if (!of_property_read_u32(np, "gpmc,adv-wr-off", &val)) - gpmc_t->adv_wr_off = val; + of_property_read_u32(np, "gpmc,adv-on-ns", &gpmc_t->adv_on); + of_property_read_u32(np, "gpmc,adv-rd-off-ns", &gpmc_t->adv_rd_off); + of_property_read_u32(np, "gpmc,adv-wr-off-ns", &gpmc_t->adv_wr_off); /* WE signal timings */ - if (!of_property_read_u32(np, "gpmc,we-on", &val)) - gpmc_t->we_on = val; - - if (!of_property_read_u32(np, "gpmc,we-off", &val)) - gpmc_t->we_off = val; + of_property_read_u32(np, "gpmc,we-on-ns", &gpmc_t->we_on); + of_property_read_u32(np, "gpmc,we-off-ns", &gpmc_t->we_off); /* OE signal timings */ - if (!of_property_read_u32(np, "gpmc,oe-on", &val)) - gpmc_t->oe_on = val; - - if (!of_property_read_u32(np, "gpmc,oe-off", &val)) - gpmc_t->oe_off = val; + of_property_read_u32(np, "gpmc,oe-on-ns", &gpmc_t->oe_on); + of_property_read_u32(np, "gpmc,oe-off-ns", &gpmc_t->oe_off); /* access and cycle timings */ - if (!of_property_read_u32(np, "gpmc,page-burst-access", &val)) - gpmc_t->page_burst_access = val; - - if (!of_property_read_u32(np, "gpmc,access", &val)) - gpmc_t->access = val; - - if (!of_property_read_u32(np, "gpmc,rd-cycle", &val)) - gpmc_t->rd_cycle = val; - - if (!of_property_read_u32(np, "gpmc,wr-cycle", &val)) - gpmc_t->wr_cycle = val; - - /* only for OMAP3430 */ - if (!of_property_read_u32(np, "gpmc,wr-access", &val)) - gpmc_t->wr_access = val; - - if (!of_property_read_u32(np, "gpmc,wr-data-mux-bus", &val)) - gpmc_t->wr_data_mux_bus = val; + of_property_read_u32(np, "gpmc,page-burst-access-ns", + &gpmc_t->page_burst_access); + of_property_read_u32(np, "gpmc,access-ns", &gpmc_t->access); + of_property_read_u32(np, "gpmc,rd-cycle-ns", &gpmc_t->rd_cycle); + of_property_read_u32(np, "gpmc,wr-cycle-ns", &gpmc_t->wr_cycle); + of_property_read_u32(np, "gpmc,bus-turnaround-ns", + &gpmc_t->bus_turnaround); + of_property_read_u32(np, "gpmc,cycle2cycle-delay-ns", + &gpmc_t->cycle2cycle_delay); + of_property_read_u32(np, "gpmc,wait-monitoring-ns", + &gpmc_t->wait_monitoring); + of_property_read_u32(np, "gpmc,clk-activation-ns", + &gpmc_t->clk_activation); + + /* only applicable to OMAP3+ */ + of_property_read_u32(np, "gpmc,wr-access-ns", &gpmc_t->wr_access); + of_property_read_u32(np, "gpmc,wr-data-mux-bus-ns", + &gpmc_t->wr_data_mux_bus); + + /* bool timing parameters */ + p = &gpmc_t->bool_timings; + + p->cycle2cyclediffcsen = + of_property_read_bool(np, "gpmc,cycle2cycle-diffcsen"); + p->cycle2cyclesamecsen = + of_property_read_bool(np, "gpmc,cycle2cycle-samecsen"); + p->we_extra_delay = of_property_read_bool(np, "gpmc,we-extra-delay"); + p->oe_extra_delay = of_property_read_bool(np, "gpmc,oe-extra-delay"); + p->adv_extra_delay = of_property_read_bool(np, "gpmc,adv-extra-delay"); + p->cs_extra_delay = of_property_read_bool(np, "gpmc,cs-extra-delay"); + p->time_para_granularity = + of_property_read_bool(np, "gpmc,time-para-granularity"); } #ifdef CONFIG_MTD_NAND @@ -1295,6 +1428,81 @@ static int gpmc_probe_onenand_child(struct platform_device *pdev, } #endif +/** + * gpmc_probe_generic_child - configures the gpmc for a child device + * @pdev: pointer to gpmc platform device + * @child: pointer to device-tree node for child device + * + * Allocates and configures a GPMC chip-select for a child device. + * Returns 0 on success and appropriate negative error code on failure. + */ +static int gpmc_probe_generic_child(struct platform_device *pdev, + struct device_node *child) +{ + struct gpmc_settings gpmc_s; + struct gpmc_timings gpmc_t; + struct resource res; + unsigned long base; + int ret, cs; + + if (of_property_read_u32(child, "reg", &cs) < 0) { + dev_err(&pdev->dev, "%s has no 'reg' property\n", + child->full_name); + return -ENODEV; + } + + if (of_address_to_resource(child, 0, &res) < 0) { + dev_err(&pdev->dev, "%s has malformed 'reg' property\n", + child->full_name); + return -ENODEV; + } + + ret = gpmc_cs_request(cs, resource_size(&res), &base); + if (ret < 0) { + dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs); + return ret; + } + + /* + * FIXME: gpmc_cs_request() will map the CS to an arbitary + * location in the gpmc address space. When booting with + * device-tree we want the NOR flash to be mapped to the + * location specified in the device-tree blob. So remap the + * CS to this location. Once DT migration is complete should + * just make gpmc_cs_request() map a specific address. + */ + ret = gpmc_cs_remap(cs, res.start); + if (ret < 0) { + dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n", + cs, res.start); + goto err; + } + + gpmc_read_settings_dt(child, &gpmc_s); + + ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width); + if (ret < 0) + goto err; + + ret = gpmc_cs_program_settings(cs, &gpmc_s); + if (ret < 0) + goto err; + + gpmc_read_timings_dt(child, &gpmc_t); + gpmc_cs_set_timings(cs, &gpmc_t); + + if (of_platform_device_create(child, NULL, &pdev->dev)) + return 0; + + dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name); + ret = -ENODEV; + +err: + gpmc_cs_free(cs); + + return ret; +} + static int gpmc_probe_dt(struct platform_device *pdev) { int ret; @@ -1305,6 +1513,13 @@ static int gpmc_probe_dt(struct platform_device *pdev) if (!of_id) return 0; + ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins", + &gpmc_nr_waitpins); + if (ret < 0) { + pr_err("%s: number of wait pins not found!\n", __func__); + return ret; + } + for_each_node_by_name(child, "nand") { ret = gpmc_probe_nand_child(pdev, child); if (ret < 0) { @@ -1320,6 +1535,23 @@ static int gpmc_probe_dt(struct platform_device *pdev) return ret; } } + + for_each_node_by_name(child, "nor") { + ret = gpmc_probe_generic_child(pdev, child); + if (ret < 0) { + of_node_put(child); + return ret; + } + } + + for_each_node_by_name(child, "ethernet") { + ret = gpmc_probe_generic_child(pdev, child); + if (ret < 0) { + of_node_put(child); + return ret; + } + } + return 0; } #else @@ -1364,18 +1596,27 @@ static int gpmc_probe(struct platform_device *pdev) gpmc_dev = &pdev->dev; l = gpmc_read_reg(GPMC_REVISION); + + /* + * FIXME: Once device-tree migration is complete the below flags + * should be populated based upon the device-tree compatible + * string. For now just use the IP revision. OMAP3+ devices have + * the wr_access and wr_data_mux_bus register fields. OMAP4+ + * devices support the addr-addr-data multiplex protocol. + * + * GPMC IP revisions: + * - OMAP24xx = 2.0 + * - OMAP3xxx = 5.0 + * - OMAP44xx/54xx/AM335x = 6.0 + */ if (GPMC_REVISION_MAJOR(l) > 0x4) gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS; + if (GPMC_REVISION_MAJOR(l) > 0x5) + gpmc_capability |= GPMC_HAS_MUX_AAD; dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l), GPMC_REVISION_MINOR(l)); - rc = gpmc_mem_init(); - if (rc < 0) { - clk_disable_unprepare(gpmc_l3_clk); - clk_put(gpmc_l3_clk); - dev_err(gpmc_dev, "failed to reserve memory\n"); - return rc; - } + gpmc_mem_init(); if (gpmc_setup_irq() < 0) dev_warn(gpmc_dev, "gpmc_setup_irq failed\n"); @@ -1383,6 +1624,9 @@ static int gpmc_probe(struct platform_device *pdev) /* Now the GPMC is initialised, unreserve the chip-selects */ gpmc_cs_map = 0; + if (!pdev->dev.of_node) + gpmc_nr_waitpins = GPMC_NR_WAITPINS; + rc = gpmc_probe_dt(pdev); if (rc < 0) { clk_disable_unprepare(gpmc_l3_clk); diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h index fe0a844d5007..707f6d58edd5 100644 --- a/arch/arm/mach-omap2/gpmc.h +++ b/arch/arm/mach-omap2/gpmc.h @@ -58,7 +58,7 @@ #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_MUXTYPE(val) ((val & 3) << 8) #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)) @@ -73,6 +73,13 @@ #define GPMC_IRQ_FIFOEVENTENABLE 0x01 #define GPMC_IRQ_COUNT_EVENT 0x02 +#define GPMC_BURST_4 4 /* 4 word burst */ +#define GPMC_BURST_8 8 /* 8 word burst */ +#define GPMC_BURST_16 16 /* 16 word burst */ +#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */ +#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */ +#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */ +#define GPMC_MUX_AD 2 /* Addr-Data multiplex */ /* bool type time settings */ struct gpmc_bool_timings { @@ -178,10 +185,6 @@ struct gpmc_device_timings { u8 cyc_wpl; /* write deassertion time in cycles */ u32 cyc_iaa; /* initial access time in cycles */ - bool mux; /* address & data muxed */ - bool sync_write;/* synchronous write */ - bool sync_read; /* synchronous read */ - /* extra delays */ bool ce_xdelay; bool avd_xdelay; @@ -189,28 +192,40 @@ struct gpmc_device_timings { bool we_xdelay; }; +struct gpmc_settings { + bool burst_wrap; /* enables wrap bursting */ + bool burst_read; /* enables read page/burst mode */ + bool burst_write; /* enables write page/burst mode */ + bool device_nand; /* device is NAND */ + bool sync_read; /* enables synchronous reads */ + bool sync_write; /* enables synchronous writes */ + bool wait_on_read; /* monitor wait on reads */ + bool wait_on_write; /* monitor wait on writes */ + u32 burst_len; /* page/burst length */ + u32 device_width; /* device bus width (8 or 16 bit) */ + u32 mux_add_data; /* multiplex address & data */ + u32 wait_pin; /* wait-pin to be used */ +}; + extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, - struct gpmc_device_timings *dev_t); + struct gpmc_settings *gpmc_s, + struct gpmc_device_timings *dev_t); 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_program_settings(int cs, struct gpmc_settings *p); 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); +extern int gpmc_configure(int cmd, int wval); +extern void gpmc_read_settings_dt(struct device_node *np, + struct gpmc_settings *p); #endif diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 2bef5a7e6af8..e210fa830f8d 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -55,6 +55,12 @@ #include "prm44xx.h" /* + * omap_clk_init: points to a function that does the SoC-specific + * clock initializations + */ +int (*omap_clk_init)(void); + +/* * The machine specific code may provide the extra mapping besides the * default mapping provided here. */ @@ -406,7 +412,7 @@ void __init omap2420_init_early(void) omap242x_clockdomains_init(); omap2420_hwmod_init(); omap_hwmod_init_postsetup(); - omap2420_clk_init(); + omap_clk_init = omap2420_clk_init; } void __init omap2420_init_late(void) @@ -436,7 +442,7 @@ void __init omap2430_init_early(void) omap243x_clockdomains_init(); omap2430_hwmod_init(); omap_hwmod_init_postsetup(); - omap2430_clk_init(); + omap_clk_init = omap2430_clk_init; } void __init omap2430_init_late(void) @@ -471,7 +477,7 @@ void __init omap3_init_early(void) omap3xxx_clockdomains_init(); omap3xxx_hwmod_init(); omap_hwmod_init_postsetup(); - omap3xxx_clk_init(); + omap_clk_init = omap3xxx_clk_init; } void __init omap3430_init_early(void) @@ -509,7 +515,7 @@ void __init ti81xx_init_early(void) omap3xxx_clockdomains_init(); omap3xxx_hwmod_init(); omap_hwmod_init_postsetup(); - omap3xxx_clk_init(); + omap_clk_init = omap3xxx_clk_init; } void __init omap3_init_late(void) @@ -577,7 +583,7 @@ void __init am33xx_init_early(void) am33xx_clockdomains_init(); am33xx_hwmod_init(); omap_hwmod_init_postsetup(); - am33xx_clk_init(); + omap_clk_init = am33xx_clk_init; } #endif @@ -602,7 +608,7 @@ void __init omap4430_init_early(void) omap44xx_clockdomains_init(); omap44xx_hwmod_init(); omap_hwmod_init_postsetup(); - omap4xxx_clk_init(); + omap_clk_init = omap4xxx_clk_init; } void __init omap4430_init_late(void) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 2520d46c8508..3f50f680372e 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1364,7 +1364,9 @@ static void _enable_sysc(struct omap_hwmod *oh) } if (sf & SYSC_HAS_MIDLEMODE) { - if (oh->flags & HWMOD_SWSUP_MSTANDBY) { + if (oh->flags & HWMOD_FORCE_MSTANDBY) { + idlemode = HWMOD_IDLEMODE_FORCE; + } else if (oh->flags & HWMOD_SWSUP_MSTANDBY) { idlemode = HWMOD_IDLEMODE_NO; } else { if (sf & SYSC_HAS_ENAWAKEUP) @@ -1436,7 +1438,8 @@ static void _idle_sysc(struct omap_hwmod *oh) } if (sf & SYSC_HAS_MIDLEMODE) { - if (oh->flags & HWMOD_SWSUP_MSTANDBY) { + if ((oh->flags & HWMOD_SWSUP_MSTANDBY) || + (oh->flags & HWMOD_FORCE_MSTANDBY)) { idlemode = HWMOD_IDLEMODE_FORCE; } else { if (sf & SYSC_HAS_ENAWAKEUP) diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index 28f4dea0512e..fe5962921f07 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -427,8 +427,8 @@ struct omap_hwmod_omap4_prcm { * * 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_SWSUP_MSTANDBY: 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 @@ -459,6 +459,10 @@ struct omap_hwmod_omap4_prcm { * correctly, or this is being abused to deal with some PM latency * issues -- but we're currently suffering from a shortage of * folks who are able to track these issues down properly. + * HWMOD_FORCE_MSTANDBY: Always keep MIDLEMODE bits cleared so that device + * is kept in force-standby mode. Failing to do so causes PM problems + * with musb on OMAP3630 at least. Note that musb has a dedicated register + * to control MSTANDBY signal when MIDLEMODE is set to force-standby. */ #define HWMOD_SWSUP_SIDLE (1 << 0) #define HWMOD_SWSUP_MSTANDBY (1 << 1) @@ -471,6 +475,7 @@ struct omap_hwmod_omap4_prcm { #define HWMOD_16BIT_REG (1 << 8) #define HWMOD_EXT_OPT_MAIN_CLK (1 << 9) #define HWMOD_BLOCK_WFI (1 << 10) +#define HWMOD_FORCE_MSTANDBY (1 << 11) /* * omap_hwmod._int_flags definitions diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index ac7e03ec952f..5112d04e7b79 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1707,9 +1707,14 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = { * Erratum ID: i479 idle_req / idle_ack mechanism potentially * broken when autoidle is enabled * workaround is to disable the autoidle bit at module level. + * + * Enabling the device in any other MIDLEMODE setting but force-idle + * causes core_pwrdm not enter idle states at least on OMAP3630. + * Note that musb has OTG_FORCESTDBY register that controls MSTANDBY + * signal when MIDLEMODE is set to force-idle. */ .flags = HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE - | HWMOD_SWSUP_MSTANDBY, + | HWMOD_FORCE_MSTANDBY, }; /* usb_otg_hs */ diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 0e47d2e1687c..9e0576569e07 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -2714,6 +2714,10 @@ static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = { { } }; +static struct omap_hwmod_opt_clk ocp2scp_usb_phy_opt_clks[] = { + { .role = "48mhz", .clk = "ocp2scp_usb_phy_phy_48m" }, +}; + /* ocp2scp_usb_phy */ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = { .name = "ocp2scp_usb_phy", @@ -2728,6 +2732,8 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = { }, }, .dev_attr = ocp2scp_dev_attr, + .opt_clks = ocp2scp_usb_phy_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(ocp2scp_usb_phy_opt_clks), }; /* diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 31ae76481737..fdf1c039062c 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -46,7 +46,6 @@ #include <asm/smp_twd.h> #include <asm/sched_clock.h> -#include <asm/arch_timer.h> #include "omap_hwmod.h" #include "omap_device.h" #include <plat/counter-32k.h> @@ -626,14 +625,10 @@ void __init omap4_local_timer_init(void) #ifdef CONFIG_SOC_OMAP5 void __init omap5_realtime_timer_init(void) { - int err; - omap4_sync32k_timer_init(); realtime_counter_init(); - err = arch_timer_of_register(); - if (err) - pr_err("%s: arch_timer_register failed %d\n", __func__, err); + clocksource_of_init(); } #endif /* CONFIG_SOC_OMAP5 */ diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index c5a3c6f9504e..e832bc7b8e2d 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ +#include <linux/err.h> #include <linux/string.h> #include <linux/types.h> #include <linux/errno.h> @@ -26,6 +27,24 @@ static u8 async_cs, sync_cs; static unsigned refclk_psec; +static struct gpmc_settings tusb_async = { + .wait_on_read = true, + .wait_on_write = true, + .device_width = GPMC_DEVWIDTH_16BIT, + .mux_add_data = GPMC_MUX_AD, +}; + +static struct gpmc_settings tusb_sync = { + .burst_read = true, + .burst_write = true, + .sync_read = true, + .sync_write = true, + .wait_on_read = true, + .wait_on_write = true, + .burst_len = GPMC_BURST_16, + .device_width = GPMC_DEVWIDTH_16BIT, + .mux_add_data = GPMC_MUX_AD, +}; /* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */ @@ -37,8 +56,6 @@ static int tusb_set_async_mode(unsigned sysclk_ps) memset(&dev_t, 0, sizeof(dev_t)); - dev_t.mux = true; - dev_t.t_ceasu = 8 * 1000; dev_t.t_avdasu = t_acsnh_advnh - 7000; dev_t.t_ce_avd = 1000; @@ -52,7 +69,7 @@ static int tusb_set_async_mode(unsigned sysclk_ps) dev_t.t_wpl = 300; dev_t.cyc_aavdh_we = 1; - gpmc_calc_timings(&t, &dev_t); + gpmc_calc_timings(&t, &tusb_async, &dev_t); return gpmc_cs_set_timings(async_cs, &t); } @@ -65,10 +82,6 @@ static int tusb_set_sync_mode(unsigned sysclk_ps) memset(&dev_t, 0, sizeof(dev_t)); - dev_t.mux = true; - dev_t.sync_read = true; - dev_t.sync_write = true; - dev_t.clk = 11100; dev_t.t_bacc = 1000; dev_t.t_ces = 1000; @@ -84,7 +97,7 @@ static int tusb_set_sync_mode(unsigned sysclk_ps) dev_t.cyc_wpl = 6; dev_t.t_ce_rdyz = 7000; - gpmc_calc_timings(&t, &dev_t); + gpmc_calc_timings(&t, &tusb_sync, &dev_t); return gpmc_cs_set_timings(sync_cs, &t); } @@ -165,18 +178,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data, return status; } tusb_resources[0].end = tusb_resources[0].start + 0x9ff; + tusb_async.wait_pin = waitpin; async_cs = async; - gpmc_cs_write_reg(async, GPMC_CS_CONFIG1, - GPMC_CONFIG1_PAGE_LEN(2) - | GPMC_CONFIG1_WAIT_READ_MON - | GPMC_CONFIG1_WAIT_WRITE_MON - | GPMC_CONFIG1_WAIT_PIN_SEL(waitpin) - | GPMC_CONFIG1_READTYPE_ASYNC - | GPMC_CONFIG1_WRITETYPE_ASYNC - | GPMC_CONFIG1_DEVICESIZE_16 - | GPMC_CONFIG1_DEVICETYPE_NOR - | GPMC_CONFIG1_MUXADDDATA); + status = gpmc_cs_program_settings(async_cs, &tusb_async); + if (status < 0) + return status; /* SYNC region, primarily for DMA */ status = gpmc_cs_request(sync, SZ_16M, (unsigned long *) @@ -186,21 +193,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data, return status; } tusb_resources[1].end = tusb_resources[1].start + 0x9ff; + tusb_sync.wait_pin = waitpin; sync_cs = sync; - gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1, - GPMC_CONFIG1_READMULTIPLE_SUPP - | GPMC_CONFIG1_READTYPE_SYNC - | GPMC_CONFIG1_WRITEMULTIPLE_SUPP - | GPMC_CONFIG1_WRITETYPE_SYNC - | GPMC_CONFIG1_PAGE_LEN(2) - | GPMC_CONFIG1_WAIT_READ_MON - | GPMC_CONFIG1_WAIT_WRITE_MON - | GPMC_CONFIG1_WAIT_PIN_SEL(waitpin) - | GPMC_CONFIG1_DEVICESIZE_16 - | GPMC_CONFIG1_DEVICETYPE_NOR - | GPMC_CONFIG1_MUXADDDATA - /* fclk divider gets set later */ - ); + + status = gpmc_cs_program_settings(sync_cs, &tusb_sync); + if (status < 0) + return status; /* IRQ */ status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq"); |