diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-24 09:36:37 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-24 09:36:37 +0000 |
commit | 206323c181371f3d5fab36c6d33e1fac09b61082 (patch) | |
tree | 4d06fe6c8bb10c5748004bd509919bf0df208b51 /arch/arm | |
parent | 25cf0398bdf365d027e171116aa4a281e9cd3c1c (diff) | |
parent | 28bd2c341120db346f30b3ba11b4eac06b2cc981 (diff) |
Merge branch 'davinci-next' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci into devel-stable
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-davinci/Kconfig | 19 | ||||
-rw-r--r-- | arch/arm/mach-davinci/aemif.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-da850-evm.c | 339 | ||||
-rw-r--r-- | arch/arm/mach-davinci/clock.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-davinci/da850.c | 75 | ||||
-rw-r--r-- | arch/arm/mach-davinci/devices-tnetv107x.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/da8xx.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-davinci/psc.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-davinci/time.c | 24 | ||||
-rw-r--r-- | arch/arm/mach-davinci/tnetv107x.c | 23 |
10 files changed, 462 insertions, 59 deletions
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index b77b860b36d..32f147998cd 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -61,6 +61,8 @@ config MACH_DAVINCI_EVM bool "TI DM644x EVM" default ARCH_DAVINCI_DM644x depends on ARCH_DAVINCI_DM644x + select MISC_DEVICES + select EEPROM_AT24 help Configure this option to specify the whether the board used for development is a DM644x EVM @@ -68,6 +70,8 @@ config MACH_DAVINCI_EVM config MACH_SFFSDR bool "Lyrtech SFFSDR" depends on ARCH_DAVINCI_DM644x + select MISC_DEVICES + select EEPROM_AT24 help Say Y here to select the Lyrtech Small Form Factor Software Defined Radio (SFFSDR) board. @@ -99,6 +103,8 @@ config MACH_DAVINCI_DM6467_EVM default ARCH_DAVINCI_DM646x depends on ARCH_DAVINCI_DM646x select MACH_DAVINCI_DM6467TEVM + select MISC_DEVICES + select EEPROM_AT24 help Configure this option to specify the whether the board used for development is a DM6467 EVM @@ -110,6 +116,8 @@ config MACH_DAVINCI_DM365_EVM bool "TI DM365 EVM" default ARCH_DAVINCI_DM365 depends on ARCH_DAVINCI_DM365 + select MISC_DEVICES + select EEPROM_AT24 help Configure this option to specify whether the board used for development is a DM365 EVM @@ -119,6 +127,8 @@ config MACH_DAVINCI_DA830_EVM default ARCH_DAVINCI_DA830 depends on ARCH_DAVINCI_DA830 select GPIO_PCF857X + select MISC_DEVICES + select EEPROM_AT24 help Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module. @@ -148,7 +158,6 @@ config MACH_DAVINCI_DA850_EVM bool "TI DA850/OMAP-L138/AM18x Reference Platform" default ARCH_DAVINCI_DA850 depends on ARCH_DAVINCI_DA850 - select GPIO_PCA953X help Say Y here to select the TI DA850/OMAP-L138/AM18x Evaluation Module. @@ -178,6 +187,12 @@ config DA850_UI_RMII endchoice +config GPIO_PCA953X + default MACH_DAVINCI_DA850_EVM + +config KEYBOARD_GPIO_POLLED + default MACH_DAVINCI_DA850_EVM + config MACH_TNETV107X bool "TI TNETV107X Reference Platform" default ARCH_DAVINCI_TNETV107X @@ -188,6 +203,8 @@ config MACH_TNETV107X config MACH_MITYOMAPL138 bool "Critical Link MityDSP-L138/MityARM-1808 SoM" depends on ARCH_DAVINCI_DA850 + select MISC_DEVICES + select EEPROM_AT24 help Say Y here to select the Critical Link MityDSP-L138/MityARM-1808 System on Module. Information on this SoM may be found at diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c index 9c3f500fc12..1ce70a91f2e 100644 --- a/arch/arm/mach-davinci/aemif.c +++ b/arch/arm/mach-davinci/aemif.c @@ -90,7 +90,7 @@ int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, void __iomem *base, unsigned cs) { unsigned set, val; - unsigned ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup; + int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup; unsigned offset = A1CR_OFFSET + cs * 4; struct clk *aemif_clk; unsigned long clkrate; diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index c6e11c682e4..b01fb2ab944 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -17,8 +17,10 @@ #include <linux/i2c.h> #include <linux/i2c/at24.h> #include <linux/i2c/pca953x.h> +#include <linux/input.h> #include <linux/mfd/tps6507x.h> #include <linux/gpio.h> +#include <linux/gpio_keys.h> #include <linux/platform_device.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> @@ -266,34 +268,115 @@ static inline void da850_evm_setup_emac_rmii(int rmii_sel) struct davinci_soc_info *soc_info = &davinci_soc_info; soc_info->emac_pdata->rmii_en = 1; - gpio_set_value(rmii_sel, 0); + gpio_set_value_cansleep(rmii_sel, 0); } #else static inline void da850_evm_setup_emac_rmii(int rmii_sel) { } #endif + +#define DA850_KEYS_DEBOUNCE_MS 10 +/* + * At 200ms polling interval it is possible to miss an + * event by tapping very lightly on the push button but most + * pushes do result in an event; longer intervals require the + * user to hold the button whereas shorter intervals require + * more CPU time for polling. + */ +#define DA850_GPIO_KEYS_POLL_MS 200 + +enum da850_evm_ui_exp_pins { + DA850_EVM_UI_EXP_SEL_C = 5, + DA850_EVM_UI_EXP_SEL_B, + DA850_EVM_UI_EXP_SEL_A, + DA850_EVM_UI_EXP_PB8, + DA850_EVM_UI_EXP_PB7, + DA850_EVM_UI_EXP_PB6, + DA850_EVM_UI_EXP_PB5, + DA850_EVM_UI_EXP_PB4, + DA850_EVM_UI_EXP_PB3, + DA850_EVM_UI_EXP_PB2, + DA850_EVM_UI_EXP_PB1, +}; + +static const char const *da850_evm_ui_exp[] = { + [DA850_EVM_UI_EXP_SEL_C] = "sel_c", + [DA850_EVM_UI_EXP_SEL_B] = "sel_b", + [DA850_EVM_UI_EXP_SEL_A] = "sel_a", + [DA850_EVM_UI_EXP_PB8] = "pb8", + [DA850_EVM_UI_EXP_PB7] = "pb7", + [DA850_EVM_UI_EXP_PB6] = "pb6", + [DA850_EVM_UI_EXP_PB5] = "pb5", + [DA850_EVM_UI_EXP_PB4] = "pb4", + [DA850_EVM_UI_EXP_PB3] = "pb3", + [DA850_EVM_UI_EXP_PB2] = "pb2", + [DA850_EVM_UI_EXP_PB1] = "pb1", +}; + +#define DA850_N_UI_PB 8 + +static struct gpio_keys_button da850_evm_ui_keys[] = { + [0 ... DA850_N_UI_PB - 1] = { + .type = EV_KEY, + .active_low = 1, + .wakeup = 0, + .debounce_interval = DA850_KEYS_DEBOUNCE_MS, + .code = -1, /* assigned at runtime */ + .gpio = -1, /* assigned at runtime */ + .desc = NULL, /* assigned at runtime */ + }, +}; + +static struct gpio_keys_platform_data da850_evm_ui_keys_pdata = { + .buttons = da850_evm_ui_keys, + .nbuttons = ARRAY_SIZE(da850_evm_ui_keys), + .poll_interval = DA850_GPIO_KEYS_POLL_MS, +}; + +static struct platform_device da850_evm_ui_keys_device = { + .name = "gpio-keys-polled", + .id = 0, + .dev = { + .platform_data = &da850_evm_ui_keys_pdata + }, +}; + +static void da850_evm_ui_keys_init(unsigned gpio) +{ + int i; + struct gpio_keys_button *button; + + for (i = 0; i < DA850_N_UI_PB; i++) { + button = &da850_evm_ui_keys[i]; + button->code = KEY_F8 - i; + button->desc = (char *) + da850_evm_ui_exp[DA850_EVM_UI_EXP_PB8 + i]; + button->gpio = gpio + DA850_EVM_UI_EXP_PB8 + i; + } +} + static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *c) { int sel_a, sel_b, sel_c, ret; - sel_a = gpio + 7; - sel_b = gpio + 6; - sel_c = gpio + 5; + sel_a = gpio + DA850_EVM_UI_EXP_SEL_A; + sel_b = gpio + DA850_EVM_UI_EXP_SEL_B; + sel_c = gpio + DA850_EVM_UI_EXP_SEL_C; - ret = gpio_request(sel_a, "sel_a"); + ret = gpio_request(sel_a, da850_evm_ui_exp[DA850_EVM_UI_EXP_SEL_A]); if (ret) { pr_warning("Cannot open UI expander pin %d\n", sel_a); goto exp_setup_sela_fail; } - ret = gpio_request(sel_b, "sel_b"); + ret = gpio_request(sel_b, da850_evm_ui_exp[DA850_EVM_UI_EXP_SEL_B]); if (ret) { pr_warning("Cannot open UI expander pin %d\n", sel_b); goto exp_setup_selb_fail; } - ret = gpio_request(sel_c, "sel_c"); + ret = gpio_request(sel_c, da850_evm_ui_exp[DA850_EVM_UI_EXP_SEL_C]); if (ret) { pr_warning("Cannot open UI expander pin %d\n", sel_c); goto exp_setup_selc_fail; @@ -304,6 +387,13 @@ static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio, gpio_direction_output(sel_b, 1); gpio_direction_output(sel_c, 1); + da850_evm_ui_keys_init(gpio); + ret = platform_device_register(&da850_evm_ui_keys_device); + if (ret) { + pr_warning("Could not register UI GPIO expander push-buttons"); + goto exp_setup_keys_fail; + } + ui_card_detected = 1; pr_info("DA850/OMAP-L138 EVM UI card detected\n"); @@ -313,6 +403,8 @@ static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio, return 0; +exp_setup_keys_fail: + gpio_free(sel_c); exp_setup_selc_fail: gpio_free(sel_b); exp_setup_selb_fail: @@ -324,14 +416,192 @@ exp_setup_sela_fail: static int da850_evm_ui_expander_teardown(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *c) { + platform_device_unregister(&da850_evm_ui_keys_device); + /* deselect all functionalities */ - gpio_set_value(gpio + 5, 1); - gpio_set_value(gpio + 6, 1); - gpio_set_value(gpio + 7, 1); + gpio_set_value_cansleep(gpio + DA850_EVM_UI_EXP_SEL_C, 1); + gpio_set_value_cansleep(gpio + DA850_EVM_UI_EXP_SEL_B, 1); + gpio_set_value_cansleep(gpio + DA850_EVM_UI_EXP_SEL_A, 1); + + gpio_free(gpio + DA850_EVM_UI_EXP_SEL_C); + gpio_free(gpio + DA850_EVM_UI_EXP_SEL_B); + gpio_free(gpio + DA850_EVM_UI_EXP_SEL_A); + + return 0; +} + +/* assign the baseboard expander's GPIOs after the UI board's */ +#define DA850_UI_EXPANDER_N_GPIOS ARRAY_SIZE(da850_evm_ui_exp) +#define DA850_BB_EXPANDER_GPIO_BASE (DAVINCI_N_GPIO + DA850_UI_EXPANDER_N_GPIOS) + +enum da850_evm_bb_exp_pins { + DA850_EVM_BB_EXP_DEEP_SLEEP_EN = 0, + DA850_EVM_BB_EXP_SW_RST, + DA850_EVM_BB_EXP_TP_23, + DA850_EVM_BB_EXP_TP_22, + DA850_EVM_BB_EXP_TP_21, + DA850_EVM_BB_EXP_USER_PB1, + DA850_EVM_BB_EXP_USER_LED2, + DA850_EVM_BB_EXP_USER_LED1, + DA850_EVM_BB_EXP_USER_SW1, + DA850_EVM_BB_EXP_USER_SW2, + DA850_EVM_BB_EXP_USER_SW3, + DA850_EVM_BB_EXP_USER_SW4, + DA850_EVM_BB_EXP_USER_SW5, + DA850_EVM_BB_EXP_USER_SW6, + DA850_EVM_BB_EXP_USER_SW7, + DA850_EVM_BB_EXP_USER_SW8 +}; + +static const char const *da850_evm_bb_exp[] = { + [DA850_EVM_BB_EXP_DEEP_SLEEP_EN] = "deep_sleep_en", + [DA850_EVM_BB_EXP_SW_RST] = "sw_rst", + [DA850_EVM_BB_EXP_TP_23] = "tp_23", + [DA850_EVM_BB_EXP_TP_22] = "tp_22", + [DA850_EVM_BB_EXP_TP_21] = "tp_21", + [DA850_EVM_BB_EXP_USER_PB1] = "user_pb1", + [DA850_EVM_BB_EXP_USER_LED2] = "user_led2", + [DA850_EVM_BB_EXP_USER_LED1] = "user_led1", + [DA850_EVM_BB_EXP_USER_SW1] = "user_sw1", + [DA850_EVM_BB_EXP_USER_SW2] = "user_sw2", + [DA850_EVM_BB_EXP_USER_SW3] = "user_sw3", + [DA850_EVM_BB_EXP_USER_SW4] = "user_sw4", + [DA850_EVM_BB_EXP_USER_SW5] = "user_sw5", + [DA850_EVM_BB_EXP_USER_SW6] = "user_sw6", + [DA850_EVM_BB_EXP_USER_SW7] = "user_sw7", + [DA850_EVM_BB_EXP_USER_SW8] = "user_sw8", +}; + +#define DA850_N_BB_USER_SW 8 + +static struct gpio_keys_button da850_evm_bb_keys[] = { + [0] = { + .type = EV_KEY, + .active_low = 1, + .wakeup = 0, + .debounce_interval = DA850_KEYS_DEBOUNCE_MS, + .code = KEY_PROG1, + .desc = NULL, /* assigned at runtime */ + .gpio = -1, /* assigned at runtime */ + }, + [1 ... DA850_N_BB_USER_SW] = { + .type = EV_SW, + .active_low = 1, + .wakeup = 0, + .debounce_interval = DA850_KEYS_DEBOUNCE_MS, + .code = -1, /* assigned at runtime */ + .desc = NULL, /* assigned at runtime */ + .gpio = -1, /* assigned at runtime */ + }, +}; + +static struct gpio_keys_platform_data da850_evm_bb_keys_pdata = { + .buttons = da850_evm_bb_keys, + .nbuttons = ARRAY_SIZE(da850_evm_bb_keys), + .poll_interval = DA850_GPIO_KEYS_POLL_MS, +}; + +static struct platform_device da850_evm_bb_keys_device = { + .name = "gpio-keys-polled", + .id = 1, + .dev = { + .platform_data = &da850_evm_bb_keys_pdata + }, +}; + +static void da850_evm_bb_keys_init(unsigned gpio) +{ + int i; + struct gpio_keys_button *button; + + button = &da850_evm_bb_keys[0]; + button->desc = (char *) + da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_PB1]; + button->gpio = gpio + DA850_EVM_BB_EXP_USER_PB1; + + for (i = 0; i < DA850_N_BB_USER_SW; i++) { + button = &da850_evm_bb_keys[i + 1]; + button->code = SW_LID + i; + button->desc = (char *) + da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_SW1 + i]; + button->gpio = gpio + DA850_EVM_BB_EXP_USER_SW1 + i; + } +} - gpio_free(gpio + 5); - gpio_free(gpio + 6); - gpio_free(gpio + 7); +#define DA850_N_BB_USER_LED 2 + +static struct gpio_led da850_evm_bb_leds[] = { + [0 ... DA850_N_BB_USER_LED - 1] = { + .active_low = 1, + .gpio = -1, /* assigned at runtime */ + .name = NULL, /* assigned at runtime */ + }, +}; + +static struct gpio_led_platform_data da850_evm_bb_leds_pdata = { + .leds = da850_evm_bb_leds, + .num_leds = ARRAY_SIZE(da850_evm_bb_leds), +}; + +static struct platform_device da850_evm_bb_leds_device = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &da850_evm_bb_leds_pdata + } +}; + +static void da850_evm_bb_leds_init(unsigned gpio) +{ + int i; + struct gpio_led *led; + + for (i = 0; i < DA850_N_BB_USER_LED; i++) { + led = &da850_evm_bb_leds[i]; + + led->gpio = gpio + DA850_EVM_BB_EXP_USER_LED2 + i; + led->name = + da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_LED2 + i]; + } +} + +static int da850_evm_bb_expander_setup(struct i2c_client *client, + unsigned gpio, unsigned ngpio, + void *c) +{ + int ret; + + /* + * Register the switches and pushbutton on the baseboard as a gpio-keys + * device. + */ + da850_evm_bb_keys_init(gpio); + ret = platform_device_register(&da850_evm_bb_keys_device); + if (ret) { + pr_warning("Could not register baseboard GPIO expander keys"); + goto io_exp_setup_sw_fail; + } + + da850_evm_bb_leds_init(gpio); + ret = platform_device_register(&da850_evm_bb_leds_device); + if (ret) { + pr_warning("Could not register baseboard GPIO expander LEDS"); + goto io_exp_setup_leds_fail; + } + + return 0; + +io_exp_setup_leds_fail: + platform_device_unregister(&da850_evm_bb_keys_device); +io_exp_setup_sw_fail: + return ret; +} + +static int da850_evm_bb_expander_teardown(struct i2c_client *client, + unsigned gpio, unsigned ngpio, void *c) +{ + platform_device_unregister(&da850_evm_bb_leds_device); + platform_device_unregister(&da850_evm_bb_keys_device); return 0; } @@ -340,6 +610,14 @@ static struct pca953x_platform_data da850_evm_ui_expander_info = { .gpio_base = DAVINCI_N_GPIO, .setup = da850_evm_ui_expander_setup, .teardown = da850_evm_ui_expander_teardown, + .names = da850_evm_ui_exp, +}; + +static struct pca953x_platform_data da850_evm_bb_expander_info = { + .gpio_base = DA850_BB_EXPANDER_GPIO_BASE, + .setup = da850_evm_bb_expander_setup, + .teardown = da850_evm_bb_expander_teardown, + .names = da850_evm_bb_exp, }; static struct i2c_board_info __initdata da850_evm_i2c_devices[] = { @@ -350,6 +628,10 @@ static struct i2c_board_info __initdata da850_evm_i2c_devices[] = { I2C_BOARD_INFO("tca6416", 0x20), .platform_data = &da850_evm_ui_expander_info, }, + { + I2C_BOARD_INFO("tca6416", 0x21), + .platform_data = &da850_evm_bb_expander_info, + }, }; static struct davinci_i2c_platform_data da850_evm_i2c_0_pdata = { @@ -540,7 +822,7 @@ static struct regulator_init_data tps65070_regulator_data[] = { { .constraints = { .min_uV = 950000, - .max_uV = 1320000, + .max_uV = 1350000, .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS), .boot_on = 1, @@ -591,7 +873,7 @@ static struct tps6507x_board tps_board = { .tps6507x_ts_init_data = &tps6507x_touchscreen_data, }; -static struct i2c_board_info __initdata da850evm_tps65070_info[] = { +static struct i2c_board_info __initdata da850_evm_tps65070_info[] = { { I2C_BOARD_INFO("tps6507x", 0x48), .platform_data = &tps_board, @@ -600,8 +882,8 @@ static struct i2c_board_info __initdata da850evm_tps65070_info[] = { static int __init pmic_tps65070_init(void) { - return i2c_register_board_info(1, da850evm_tps65070_info, - ARRAY_SIZE(da850evm_tps65070_info)); + return i2c_register_board_info(1, da850_evm_tps65070_info, + ARRAY_SIZE(da850_evm_tps65070_info)); } static const short da850_evm_lcdc_pins[] = { @@ -736,6 +1018,27 @@ static struct edma_rsv_info *da850_edma_rsv[2] = { &da850_edma_cc1_rsv, }; +#ifdef CONFIG_CPU_FREQ +static __init int da850_evm_init_cpufreq(void) +{ + switch (system_rev & 0xF) { + case 3: + da850_max_speed = 456000; + break; + case 2: + da850_max_speed = 408000; + break; + case 1: + da850_max_speed = 372000; + break; + } + + return da850_register_cpufreq("pll0_sysclk3"); +} +#else +static __init int da850_evm_init_cpufreq(void) { return 0; } +#endif + static __init void da850_evm_init(void) { int ret; @@ -836,7 +1139,7 @@ static __init void da850_evm_init(void) if (ret) pr_warning("da850_evm_init: rtc setup failed: %d\n", ret); - ret = da850_register_cpufreq("pll0_sysclk3"); + ret = da850_evm_init_cpufreq(); if (ret) pr_warning("da850_evm_init: cpufreq registration failed: %d\n", ret); diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 01ba080433d..e4e3af179f0 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -336,7 +336,7 @@ int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate) ratio--; } - if (ratio > PLLDIV_RATIO_MASK) + if (ratio > pll->div_ratio_mask) return -EINVAL; do { @@ -344,7 +344,7 @@ int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate) } while (v & PLLSTAT_GOSTAT); v = __raw_readl(pll->base + clk->div_reg); - v &= ~PLLDIV_RATIO_MASK; + v &= ~pll->div_ratio_mask; v |= ratio | PLLDIV_EN; __raw_writel(v, pll->base + clk->div_reg); diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 63916b90276..78b5ae29ae4 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -830,8 +830,7 @@ static void da850_set_async3_src(int pllnum) * According to the TRM, minimum PLLM results in maximum power savings. * The OPP definitions below should keep the PLLM as low as possible. * - * The output of the PLLM must be between 400 to 600 MHz. - * This rules out prediv of anything but divide-by-one for 24Mhz OSC input. + * The output of the PLLM must be between 300 to 600 MHz. */ struct da850_opp { unsigned int freq; /* in KHz */ @@ -842,6 +841,33 @@ struct da850_opp { unsigned int cvdd_max; /* in uV */ }; +static const struct da850_opp da850_opp_456 = { + .freq = 456000, + .prediv = 1, + .mult = 19, + .postdiv = 1, + .cvdd_min = 1300000, + .cvdd_max = 1350000, +}; + +static const struct da850_opp da850_opp_408 = { + .freq = 408000, + .prediv = 1, + .mult = 17, + .postdiv = 1, + .cvdd_min = 1300000, + .cvdd_max = 1350000, +}; + +static const struct da850_opp da850_opp_372 = { + .freq = 372000, + .prediv = 2, + .mult = 31, + .postdiv = 1, + .cvdd_min = 1200000, + .cvdd_max = 1320000, +}; + static const struct da850_opp da850_opp_300 = { .freq = 300000, .prediv = 1, @@ -876,6 +902,9 @@ static const struct da850_opp da850_opp_96 = { } static struct cpufreq_frequency_table da850_freq_table[] = { + OPP(456), + OPP(408), + OPP(372), OPP(300), OPP(200), OPP(96), @@ -886,6 +915,19 @@ static struct cpufreq_frequency_table da850_freq_table[] = { }; #ifdef CONFIG_REGULATOR +static int da850_set_voltage(unsigned int index); +static int da850_regulator_init(void); +#endif + +static struct davinci_cpufreq_config cpufreq_info = { + .freq_table = da850_freq_table, +#ifdef CONFIG_REGULATOR + .init = da850_regulator_init, + .set_voltage = da850_set_voltage, +#endif +}; + +#ifdef CONFIG_REGULATOR static struct regulator *cvdd; static int da850_set_voltage(unsigned int index) @@ -895,7 +937,7 @@ static int da850_set_voltage(unsigned int index) if (!cvdd) return -ENODEV; - opp = (struct da850_opp *) da850_freq_table[index].index; + opp = (struct da850_opp *) cpufreq_info.freq_table[index].index; return regulator_set_voltage(cvdd, opp->cvdd_min, opp->cvdd_max); } @@ -912,14 +954,6 @@ static int da850_regulator_init(void) } #endif -static struct davinci_cpufreq_config cpufreq_info = { - .freq_table = &da850_freq_table[0], -#ifdef CONFIG_REGULATOR - .init = da850_regulator_init, - .set_voltage = da850_set_voltage, -#endif -}; - static struct platform_device da850_cpufreq_device = { .name = "cpufreq-davinci", .dev = { @@ -928,12 +962,22 @@ static struct platform_device da850_cpufreq_device = { .id = -1, }; +unsigned int da850_max_speed = 300000; + int __init da850_register_cpufreq(char *async_clk) { + int i; + /* cpufreq driver can help keep an "async" clock constant */ if (async_clk) clk_add_alias("async", da850_cpufreq_device.name, async_clk, NULL); + for (i = 0; i < ARRAY_SIZE(da850_freq_table); i++) { + if (da850_freq_table[i].frequency <= da850_max_speed) { + cpufreq_info.freq_table = &da850_freq_table[i]; + break; + } + } return platform_device_register(&da850_cpufreq_device); } @@ -942,17 +986,18 @@ static int da850_round_armrate(struct clk *clk, unsigned long rate) { int i, ret = 0, diff; unsigned int best = (unsigned int) -1; + struct cpufreq_frequency_table *table = cpufreq_info.freq_table; rate /= 1000; /* convert to kHz */ - for (i = 0; da850_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { - diff = da850_freq_table[i].frequency - rate; + for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { + diff = table[i].frequency - rate; if (diff < 0) diff = -diff; if (diff < best) { best = diff; - ret = da850_freq_table[i].frequency; + ret = table[i].frequency; } } @@ -973,7 +1018,7 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index) struct pll_data *pll = clk->pll_data; int ret; - opp = (struct da850_opp *) da850_freq_table[index].index; + opp = (struct da850_opp *) cpufreq_info.freq_table[index].index; prediv = opp->prediv; mult = opp->mult; postdiv = opp->postdiv; diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index c9a86d8130d..85503debda5 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c @@ -344,7 +344,20 @@ static struct platform_device tsc_device = { void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) { - int i; + int i, error; + struct clk *tsc_clk; + + /* + * The reset defaults for tnetv107x tsc clock divider is set too high. + * This forces the clock down to a range that allows the ADC to + * complete sample conversion in time. + */ + tsc_clk = clk_get(NULL, "sys_tsc_clk"); + if (tsc_clk) { + error = clk_set_rate(tsc_clk, 5000000); + WARN_ON(error < 0); + clk_put(tsc_clk); + } platform_device_register(&edma_device); platform_device_register(&tnetv107x_wdt_device); diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index 4247b3f53b3..e7f95206652 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -28,6 +28,13 @@ extern void __iomem *da8xx_syscfg0_base; extern void __iomem *da8xx_syscfg1_base; /* + * If the DA850/OMAP-L138/AM18x SoC on board is of a higher speed grade + * (than the regular 300Mhz variant), the board code should set this up + * with the supported speed before calling da850_register_cpufreq(). + */ +extern unsigned int da850_max_speed; + +/* * The cp_intc interrupt controller for the da8xx isn't in the same * chunk of physical memory space as the other registers (like it is * on the davincis) so it needs to be mapped separately. It will be diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index 1b15dbd0a77..a4158040070 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -83,21 +83,16 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, pdctl1 = __raw_readl(psc_base + PDCTL1); pdctl1 |= 0x100; __raw_writel(pdctl1, psc_base + PDCTL1); - - do { - ptstat = __raw_readl(psc_base + - PTSTAT); - } while (!(((ptstat >> domain) & 1) == 0)); } else { ptcmd = 1 << domain; __raw_writel(ptcmd, psc_base + PTCMD); - - do { - ptstat = __raw_readl(psc_base + PTSTAT); - } while (!(((ptstat >> domain) & 1) == 0)); } do { + ptstat = __raw_readl(psc_base + PTSTAT); + } while (!(((ptstat >> domain) & 1) == 0)); + + do { mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); } while (!((mdstat & MDSTAT_STATE_MASK) == next_state)); diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 0f21c36e65d..5d1eea02663 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -272,15 +272,36 @@ static cycle_t read_cycles(struct clocksource *cs) return (cycles_t)timer32_read(t); } +/* + * Kernel assumes that sched_clock can be called early but may not have + * things ready yet. + */ +static cycle_t read_dummy(struct clocksource *cs) +{ + return 0; +} + + static struct clocksource clocksource_davinci = { .rating = 300, - .read = read_cycles, + .read = read_dummy, .mask = CLOCKSOURCE_MASK(32), .shift = 24, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; /* + * Overwrite weak default sched_clock with something more precise + */ +unsigned long long notrace sched_clock(void) +{ + const cycle_t cyc = clocksource_davinci.read(&clocksource_davinci); + + return clocksource_cyc2ns(cyc, clocksource_davinci.mult, + clocksource_davinci.shift); +} + +/* * clockevent */ static int davinci_set_next_event(unsigned long cycles, @@ -377,6 +398,7 @@ static void __init davinci_timer_init(void) davinci_clock_tick_rate = clk_get_rate(timer_clk); /* setup clocksource */ + clocksource_davinci.read = read_cycles; clocksource_davinci.name = id_to_name[clocksource_id]; clocksource_davinci.mult = clocksource_khz2mult(davinci_clock_tick_rate/1000, diff --git a/arch/arm/mach-davinci/tnetv107x.c b/arch/arm/mach-davinci/tnetv107x.c index daeae06430b..6fcdecec8d8 100644 --- a/arch/arm/mach-davinci/tnetv107x.c +++ b/arch/arm/mach-davinci/tnetv107x.c @@ -131,12 +131,13 @@ define_pll_clk(tdm, 1, 0x0ff, 0x200); define_pll_clk(eth, 2, 0x0ff, 0x400); /* Level 2 - divided outputs from the PLLs */ -#define define_pll_div_clk(pll, cname, div) \ - static struct clk pll##_##cname##_clk = { \ - .name = #pll "_" #cname "_clk",\ - .parent = &pll_##pll##_clk, \ - .flags = CLK_PLL, \ - .div_reg = PLLDIV##div, \ +#define define_pll_div_clk(pll, cname, div) \ + static struct clk pll##_##cname##_clk = { \ + .name = #pll "_" #cname "_clk", \ + .parent = &pll_##pll##_clk, \ + .flags = CLK_PLL, \ + .div_reg = PLLDIV##div, \ + .set_rate = davinci_set_sysclk_rate, \ } define_pll_div_clk(sys, arm1176, 1); @@ -192,6 +193,7 @@ lpsc_clk_enabled(system, sys_half_clk, SYSTEM); lpsc_clk_enabled(ddr2_vrst, sys_ddr_clk, DDR2_EMIF1_VRST); lpsc_clk_enabled(ddr2_vctl_rst, sys_ddr_clk, DDR2_EMIF2_VCTL_RST); lpsc_clk_enabled(wdt_arm, sys_half_clk, WDT_ARM); +lpsc_clk_enabled(timer1, sys_half_clk, TIMER1); lpsc_clk(mbx_lite, sys_arm1176_clk, MBX_LITE); lpsc_clk(ethss, eth_125mhz_clk, ETHSS); @@ -205,16 +207,15 @@ lpsc_clk(mdio, sys_half_clk, MDIO); lpsc_clk(sdio0, sys_half_clk, SDIO0); lpsc_clk(sdio1, sys_half_clk, SDIO1); lpsc_clk(timer0, sys_half_clk, TIMER0); -lpsc_clk(timer1, sys_half_clk, TIMER1); lpsc_clk(wdt_dsp, sys_half_clk, WDT_DSP); lpsc_clk(ssp, sys_half_clk, SSP); lpsc_clk(tdm0, tdm_0_clk, TDM0); lpsc_clk(tdm1, tdm_1_clk, TDM1); lpsc_clk(vlynq, sys_vlynq_ref_clk, VLYNQ); lpsc_clk(mcdma, sys_half_clk, MCDMA); -lpsc_clk(usb0, sys_half_clk, USB0); -lpsc_clk(usb1, sys_half_clk, USB1); lpsc_clk(usbss, sys_half_clk, USBSS); +lpsc_clk(usb0, clk_usbss, USB0); +lpsc_clk(usb1, clk_usbss, USB1); lpsc_clk(ethss_rgmii, eth_250mhz_clk, ETHSS_RGMII); lpsc_clk(imcop, sys_dsp_clk, IMCOP); lpsc_clk(spare, sys_half_clk, SPARE); @@ -281,7 +282,9 @@ static struct clk_lookup clks[] = { CLK(NULL, "clk_tdm0", &clk_tdm0), CLK(NULL, "clk_vlynq", &clk_vlynq), CLK(NULL, "clk_mcdma", &clk_mcdma), + CLK(NULL, "clk_usbss", &clk_usbss), CLK(NULL, "clk_usb0", &clk_usb0), + CLK(NULL, "clk_usb1", &clk_usb1), CLK(NULL, "clk_tdm1", &clk_tdm1), CLK(NULL, "clk_debugss", &clk_debugss), CLK(NULL, "clk_ethss_rgmii", &clk_ethss_rgmii), @@ -289,8 +292,6 @@ static struct clk_lookup clks[] = { CLK(NULL, "clk_imcop", &clk_imcop), CLK(NULL, "clk_spare", &clk_spare), CLK("davinci_mmc.1", NULL, &clk_sdio1), - CLK(NULL, "clk_usb1", &clk_usb1), - CLK(NULL, "clk_usbss", &clk_usbss), CLK(NULL, "clk_ddr2_vrst", &clk_ddr2_vrst), CLK(NULL, "clk_ddr2_vctl_rst", &clk_ddr2_vctl_rst), CLK(NULL, NULL, NULL), |