diff options
Diffstat (limited to 'arch/arm/mach-davinci')
-rw-r--r-- | arch/arm/mach-davinci/Kconfig | 18 | ||||
-rw-r--r-- | arch/arm/mach-davinci/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-da850-evm.c | 90 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-dm365-evm.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-dm644x-evm.c | 32 | ||||
-rw-r--r-- | arch/arm/mach-davinci/da830.c | 45 | ||||
-rw-r--r-- | arch/arm/mach-davinci/da850.c | 50 | ||||
-rw-r--r-- | arch/arm/mach-davinci/davinci.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-davinci/devices-da8xx.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-davinci/devices.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm355.c | 28 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm365.c | 30 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm644x.c | 28 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm646x.c | 30 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/common.h | 17 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/time.h | 35 | ||||
-rw-r--r-- | arch/arm/mach-davinci/time.c | 414 |
17 files changed, 247 insertions, 620 deletions
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 5a59cebc7d0a..02b180ad7245 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -1,11 +1,23 @@ # SPDX-License-Identifier: GPL-2.0 + +menuconfig ARCH_DAVINCI + bool "TI DaVinci" + depends on ARCH_MULTI_V5 + select DAVINCI_TIMER + select ZONE_DMA + select ARCH_HAS_HOLES_MEMORYMODEL + select PM_GENERIC_DOMAINS if PM + select PM_GENERIC_DOMAINS_OF if PM && OF + select REGMAP_MMIO + select RESET_CONTROLLER + select HAVE_IDE + select PINCTRL_SINGLE + if ARCH_DAVINCI config ARCH_DAVINCI_DMx bool -menu "TI DaVinci Implementations" - comment "DaVinci Core Type" config ARCH_DAVINCI_DM644x @@ -225,6 +237,4 @@ config DAVINCI_MUX_WARNINGS to change the pin multiplexing setup. When there are no warnings printed, it's safe to deselect DAVINCI_MUX for your product. -endmenu - endif diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index f76a8482784f..58838a9de651 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -4,9 +4,10 @@ # # +ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include + # Common objects -obj-y := time.o serial.o usb.o \ - common.o sram.o +obj-y := serial.o usb.o common.o sram.o obj-$(CONFIG_DAVINCI_MUX) += mux.o diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 0628e7d7dcf3..5b3549f1236c 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -36,6 +36,7 @@ #include <linux/platform_data/ti-aemif.h> #include <linux/platform_data/spi-davinci.h> #include <linux/platform_data/uio_pruss.h> +#include <linux/property.h> #include <linux/regulator/machine.h> #include <linux/regulator/tps6507x.h> #include <linux/regulator/fixed.h> @@ -802,37 +803,79 @@ static const short da850_evm_mmcsd0_pins[] __initconst = { -1 }; -static void da850_panel_power_ctrl(int val) -{ - /* lcd backlight */ - gpio_set_value(DA850_LCD_BL_PIN, val); +static struct property_entry da850_lcd_backlight_props[] = { + PROPERTY_ENTRY_BOOL("default-on"), + { } +}; - /* lcd power */ - gpio_set_value(DA850_LCD_PWR_PIN, val); -} +static struct gpiod_lookup_table da850_lcd_backlight_gpio_table = { + .dev_id = "gpio-backlight", + .table = { + GPIO_LOOKUP("davinci_gpio", DA850_LCD_BL_PIN, NULL, 0), + { } + }, +}; + +static const struct platform_device_info da850_lcd_backlight_info = { + .name = "gpio-backlight", + .id = PLATFORM_DEVID_NONE, + .properties = da850_lcd_backlight_props, +}; + +static struct regulator_consumer_supply da850_lcd_supplies[] = { + REGULATOR_SUPPLY("lcd", NULL), +}; + +static struct regulator_init_data da850_lcd_supply_data = { + .consumer_supplies = da850_lcd_supplies, + .num_consumer_supplies = ARRAY_SIZE(da850_lcd_supplies), + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +static struct fixed_voltage_config da850_lcd_supply = { + .supply_name = "lcd", + .microvolts = 33000000, + .init_data = &da850_lcd_supply_data, +}; + +static struct platform_device da850_lcd_supply_device = { + .name = "reg-fixed-voltage", + .id = 1, /* Dummy fixed regulator is 0 */ + .dev = { + .platform_data = &da850_lcd_supply, + }, +}; + +static struct gpiod_lookup_table da850_lcd_supply_gpio_table = { + .dev_id = "reg-fixed-voltage.1", + .table = { + GPIO_LOOKUP("davinci_gpio", DA850_LCD_PWR_PIN, NULL, 0), + { } + }, +}; + +static struct gpiod_lookup_table *da850_lcd_gpio_lookups[] = { + &da850_lcd_backlight_gpio_table, + &da850_lcd_supply_gpio_table, +}; static int da850_lcd_hw_init(void) { + struct platform_device *backlight; int status; - status = gpio_request(DA850_LCD_BL_PIN, "lcd bl"); - if (status < 0) - return status; - - status = gpio_request(DA850_LCD_PWR_PIN, "lcd pwr"); - if (status < 0) { - gpio_free(DA850_LCD_BL_PIN); - return status; - } + gpiod_add_lookup_tables(da850_lcd_gpio_lookups, + ARRAY_SIZE(da850_lcd_gpio_lookups)); - gpio_direction_output(DA850_LCD_BL_PIN, 0); - gpio_direction_output(DA850_LCD_PWR_PIN, 0); + backlight = platform_device_register_full(&da850_lcd_backlight_info); + if (IS_ERR(backlight)) + return PTR_ERR(backlight); - /* Switch off panel power and backlight */ - da850_panel_power_ctrl(0); - - /* Switch on panel power and backlight */ - da850_panel_power_ctrl(1); + status = platform_device_register(&da850_lcd_supply_device); + if (status) + return status; return 0; } @@ -1443,7 +1486,6 @@ static __init void da850_evm_init(void) if (ret) pr_warn("%s: LCD initialization failed: %d\n", __func__, ret); - sharp_lk043t1dg01_pdata.panel_power_ctrl = da850_panel_power_ctrl, ret = da8xx_register_lcdc(&sharp_lk043t1dg01_pdata); if (ret) pr_warn("%s: LCDC registration failed: %d\n", __func__, ret); diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 150a36f333df..2328b15ac067 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -30,6 +30,8 @@ #include <linux/spi/eeprom.h> #include <linux/v4l2-dv-timings.h> #include <linux/platform_data/ti-aemif.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -245,6 +247,19 @@ static struct davinci_i2c_platform_data i2c_pdata = { .bus_delay = 0 /* usec */, }; +/* Fixed regulator support */ +static struct regulator_consumer_supply fixed_supplies_3_3v[] = { + /* Baseboard 3.3V: 5V -> TPS767D301 -> 3.3V */ + REGULATOR_SUPPLY("AVDD", "1-0018"), + REGULATOR_SUPPLY("DRVDD", "1-0018"), + REGULATOR_SUPPLY("IOVDD", "1-0018"), +}; + +static struct regulator_consumer_supply fixed_supplies_1_8v[] = { + /* Baseboard 1.8V: 5V -> TPS767D301 -> 1.8V */ + REGULATOR_SUPPLY("DVDD", "1-0018"), +}; + static int dm365evm_keyscan_enable(struct device *dev) { return davinci_cfg_reg(DM365_KEYSCAN); @@ -800,6 +815,11 @@ static __init void dm365_evm_init(void) if (ret) pr_warn("%s: GPIO init failed: %d\n", __func__, ret); + regulator_register_always_on(0, "fixed-dummy", fixed_supplies_1_8v, + ARRAY_SIZE(fixed_supplies_1_8v), 1800000); + regulator_register_always_on(1, "fixed-dummy", fixed_supplies_3_3v, + ARRAY_SIZE(fixed_supplies_3_3v), 3300000); + nvmem_add_cell_table(&davinci_nvmem_cell_table); nvmem_add_cell_lookups(&davinci_nvmem_cell_lookup, 1); diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 9d87d4e440ea..3461d12bbfc0 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -29,6 +29,8 @@ #include <linux/v4l2-dv-timings.h> #include <linux/export.h> #include <linux/leds.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <media/i2c/tvp514x.h> @@ -653,6 +655,19 @@ static struct i2c_board_info __initdata i2c_info[] = { }, }; +/* Fixed regulator support */ +static struct regulator_consumer_supply fixed_supplies_3_3v[] = { + /* Baseboard 3.3V: 5V -> TPS54310PWP -> 3.3V */ + REGULATOR_SUPPLY("AVDD", "1-001b"), + REGULATOR_SUPPLY("DRVDD", "1-001b"), +}; + +static struct regulator_consumer_supply fixed_supplies_1_8v[] = { + /* Baseboard 1.8V: 5V -> TPS54310PWP -> 1.8V */ + REGULATOR_SUPPLY("IOVDD", "1-001b"), + REGULATOR_SUPPLY("DVDD", "1-001b"), +}; + #define DM644X_I2C_SDA_PIN GPIO_TO_PIN(2, 12) #define DM644X_I2C_SCL_PIN GPIO_TO_PIN(2, 11) @@ -823,6 +838,17 @@ static int davinci_phy_fixup(struct phy_device *phydev) #define HAS_NAND IS_ENABLED(CONFIG_MTD_NAND_DAVINCI) +#define GPIO_nVBUS_DRV 160 + +static struct gpiod_lookup_table dm644evm_usb_gpio_table = { + .dev_id = "musb-davinci", + .table = { + GPIO_LOOKUP("davinci_gpio", GPIO_nVBUS_DRV, NULL, + GPIO_ACTIVE_HIGH), + { } + }, +}; + static __init void davinci_evm_init(void) { int ret; @@ -831,6 +857,11 @@ static __init void davinci_evm_init(void) dm644x_register_clocks(); + regulator_register_always_on(0, "fixed-dummy", fixed_supplies_1_8v, + ARRAY_SIZE(fixed_supplies_1_8v), 1800000); + regulator_register_always_on(1, "fixed-dummy", fixed_supplies_3_3v, + ARRAY_SIZE(fixed_supplies_3_3v), 3300000); + dm644x_init_devices(); ret = dm644x_gpio_register(); @@ -875,6 +906,7 @@ static __init void davinci_evm_init(void) dm644x_init_asp(); /* irlml6401 switches over 1A, in under 8 msec */ + gpiod_add_lookup_table(&dm644evm_usb_gpio_table); davinci_setup_usb(1000, 8); if (IS_BUILTIN(CONFIG_PHYLIB)) { diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index e6b8ffd934a1..018ab4b549f1 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -21,7 +21,8 @@ #include <mach/common.h> #include <mach/cputype.h> #include <mach/da8xx.h> -#include <mach/time.h> + +#include <clocksource/timer-davinci.h> #include "irqs.h" #include "mux.h" @@ -676,32 +677,17 @@ int __init da830_register_gpio(void) return da8xx_register_gpio(&da830_gpio_platform_data); } -static struct davinci_timer_instance da830_timer_instance[2] = { - { - .base = DA8XX_TIMER64P0_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0), - .cmp_off = DA830_CMP12_0, - .cmp_irq = DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_0), - }, - { - .base = DA8XX_TIMER64P1_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_1), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_1), - .cmp_off = DA830_CMP12_0, - .cmp_irq = DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_1), - }, -}; - /* - * T0_BOT: Timer 0, bottom : Used for clock_event & clocksource - * T0_TOP: Timer 0, top : Used by DSP - * T1_BOT, T1_TOP: Timer 1, bottom & top: Used for watchdog timer + * Bottom half of timer0 is used both for clock even and clocksource. + * Top half is used by DSP. */ -static struct davinci_timer_info da830_timer_info = { - .timers = da830_timer_instance, - .clockevent_id = T0_BOT, - .clocksource_id = T0_BOT, +static const struct davinci_timer_cfg da830_timer_cfg = { + .reg = DEFINE_RES_IO(DA8XX_TIMER64P0_BASE, SZ_4K), + .irq = { + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_0)), + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0)), + }, + .cmp_off = DA830_CMP12_0, }; static const struct davinci_soc_info davinci_soc_info_da830 = { @@ -713,7 +699,6 @@ static const struct davinci_soc_info davinci_soc_info_da830 = { .pinmux_base = DA8XX_SYSCFG0_BASE + 0x120, .pinmux_pins = da830_pins, .pinmux_pins_num = ARRAY_SIZE(da830_pins), - .timer_info = &da830_timer_info, .emac_pdata = &da8xx_emac_pdata, }; @@ -743,6 +728,7 @@ void __init da830_init_time(void) { void __iomem *pll; struct clk *clk; + int rv; clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA830_REF_FREQ); @@ -751,8 +737,13 @@ void __init da830_init_time(void) da830_pll_init(NULL, pll, NULL); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } - davinci_timer_init(clk); + rv = davinci_timer_register(clk, &da830_timer_cfg); + WARN(rv, "Unable to register the timer: %d\n", rv); } static struct resource da830_psc0_resources[] = { diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 77bc64d6e39b..73b7cc53f966 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -35,7 +35,8 @@ #include <mach/cputype.h> #include <mach/da8xx.h> #include <mach/pm.h> -#include <mach/time.h> + +#include <clocksource/timer-davinci.h> #include "irqs.h" #include "mux.h" @@ -333,38 +334,16 @@ static struct davinci_id da850_ids[] = { }, }; -static struct davinci_timer_instance da850_timer_instance[4] = { - { - .base = DA8XX_TIMER64P0_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0), - }, - { - .base = DA8XX_TIMER64P1_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_1), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_1), - }, - { - .base = DA850_TIMER64P2_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT12_2), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT34_2), - }, - { - .base = DA850_TIMER64P3_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT12_3), - .top_irq = DAVINCI_INTC_IRQ(IRQ_DA850_TINT34_3), - }, -}; - /* - * T0_BOT: Timer 0, bottom : Used for clock_event - * T0_TOP: Timer 0, top : Used for clocksource - * T1_BOT, T1_TOP: Timer 1, bottom & top: Used for watchdog timer + * Bottom half of timer 0 is used for clock_event, top half for + * clocksource. */ -static struct davinci_timer_info da850_timer_info = { - .timers = da850_timer_instance, - .clockevent_id = T0_BOT, - .clocksource_id = T0_TOP, +static const struct davinci_timer_cfg da850_timer_cfg = { + .reg = DEFINE_RES_IO(DA8XX_TIMER64P0_BASE, SZ_4K), + .irq = { + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0)), + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0)), + }, }; #ifdef CONFIG_CPU_FREQ @@ -635,7 +614,6 @@ static const struct davinci_soc_info davinci_soc_info_da850 = { .pinmux_base = DA8XX_SYSCFG0_BASE + 0x120, .pinmux_pins = da850_pins, .pinmux_pins_num = ARRAY_SIZE(da850_pins), - .timer_info = &da850_timer_info, .emac_pdata = &da8xx_emac_pdata, .sram_dma = DA8XX_SHARED_RAM_BASE, .sram_len = SZ_128K, @@ -672,6 +650,7 @@ void __init da850_init_time(void) void __iomem *pll0; struct regmap *cfgchip; struct clk *clk; + int rv; clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA850_REF_FREQ); @@ -681,8 +660,13 @@ void __init da850_init_time(void) da850_pll0_init(NULL, pll0, cfgchip); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } - davinci_timer_init(clk); + rv = davinci_timer_register(clk, &da850_timer_cfg); + WARN(rv, "Unable to register the timer: %d\n", rv); } static struct resource da850_pll1_resources[] = { diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h index 56c1835c42e5..208d7a4d3597 100644 --- a/arch/arm/mach-davinci/davinci.h +++ b/arch/arm/mach-davinci/davinci.h @@ -60,6 +60,9 @@ void davinci_map_sysmod(void); #define DAVINCI_GPIO_BASE 0x01C67000 int davinci_gpio_register(struct resource *res, int size, void *pdata); +#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400) +#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00) + /* DM355 base addresses */ #define DM355_ASYNC_EMIF_CONTROL_BASE 0x01e10000 #define DM355_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 2d69e704f7f6..feb206bdf6e1 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -21,7 +21,6 @@ #include <mach/common.h> #include <mach/cputype.h> #include <mach/da8xx.h> -#include <mach/time.h> #include "asp.h" #include "cpuidle.h" diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 3e447d468845..849e811fade7 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -17,7 +17,6 @@ #include <mach/hardware.h> #include <mach/cputype.h> #include <mach/mux.h> -#include <mach/time.h> #include "davinci.h" #include "irqs.h" @@ -34,7 +33,7 @@ void __iomem *davinci_sysmod_base; void davinci_map_sysmod(void) { - davinci_sysmod_base = ioremap_nocache(DAVINCI_SYSTEM_MODULE_BASE, + davinci_sysmod_base = ioremap(DAVINCI_SYSTEM_MODULE_BASE, 0x800); /* * Throw a bug since a lot of board initialization code depends @@ -303,21 +302,3 @@ int davinci_gpio_register(struct resource *res, int size, void *pdata) davinci_gpio_device.dev.platform_data = pdata; return platform_device_register(&davinci_gpio_device); } - -/*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------------------*/ - -struct davinci_timer_instance davinci_timer_instance[2] = { - { - .base = DAVINCI_TIMER0_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12), - .top_irq = DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34), - }, - { - .base = DAVINCI_TIMER1_BASE, - .bottom_irq = DAVINCI_INTC_IRQ(IRQ_TINT1_TINT12), - .top_irq = DAVINCI_INTC_IRQ(IRQ_TINT1_TINT34), - }, -}; - diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index c6073326be2e..5de72d2fa8f0 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -30,7 +30,8 @@ #include <mach/cputype.h> #include <mach/mux.h> #include <mach/serial.h> -#include <mach/time.h> + +#include <clocksource/timer-davinci.h> #include "asp.h" #include "davinci.h" @@ -620,15 +621,15 @@ static struct davinci_id dm355_ids[] = { }; /* - * T0_BOT: Timer 0, bottom: clockevent source for hrtimers - * T0_TOP: Timer 0, top : clocksource for generic timekeeping - * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) - * T1_TOP: Timer 1, top : <unused> + * Bottom half of timer0 is used for clockevent, top half is used for + * clocksource. */ -static struct davinci_timer_info dm355_timer_info = { - .timers = davinci_timer_instance, - .clockevent_id = T0_BOT, - .clocksource_id = T0_TOP, +static const struct davinci_timer_cfg dm355_timer_cfg = { + .reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K), + .irq = { + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)), + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)), + }, }; static struct plat_serial8250_port dm355_serial0_platform_data[] = { @@ -706,7 +707,6 @@ static const struct davinci_soc_info davinci_soc_info_dm355 = { .pinmux_base = DAVINCI_SYSTEM_MODULE_BASE, .pinmux_pins = dm355_pins, .pinmux_pins_num = ARRAY_SIZE(dm355_pins), - .timer_info = &dm355_timer_info, .sram_dma = 0x00010000, .sram_len = SZ_32K, }; @@ -733,6 +733,7 @@ void __init dm355_init_time(void) { void __iomem *pll1, *psc; struct clk *clk; + int rv; clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM355_REF_FREQ); @@ -743,8 +744,13 @@ void __init dm355_init_time(void) dm355_psc_init(NULL, psc); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } - davinci_timer_init(clk); + rv = davinci_timer_register(clk, &dm355_timer_cfg); + WARN(rv, "Unable to register the timer: %d\n", rv); } static struct resource dm355_pll2_resources[] = { diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 2f9ae6431bf5..c1e0d46996e4 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -35,7 +35,8 @@ #include <mach/cputype.h> #include <mach/mux.h> #include <mach/serial.h> -#include <mach/time.h> + +#include <clocksource/timer-davinci.h> #include "asp.h" #include "davinci.h" @@ -462,8 +463,8 @@ static s8 dm365_queue_priority_mapping[][2] = { }; static const struct dma_slave_map dm365_edma_map[] = { - { "davinci-mcbsp.0", "tx", EDMA_FILTER_PARAM(0, 2) }, - { "davinci-mcbsp.0", "rx", EDMA_FILTER_PARAM(0, 3) }, + { "davinci-mcbsp", "tx", EDMA_FILTER_PARAM(0, 2) }, + { "davinci-mcbsp", "rx", EDMA_FILTER_PARAM(0, 3) }, { "davinci_voicecodec", "tx", EDMA_FILTER_PARAM(0, 2) }, { "davinci_voicecodec", "rx", EDMA_FILTER_PARAM(0, 3) }, { "spi_davinci.2", "tx", EDMA_FILTER_PARAM(0, 10) }, @@ -660,10 +661,16 @@ static struct davinci_id dm365_ids[] = { }, }; -static struct davinci_timer_info dm365_timer_info = { - .timers = davinci_timer_instance, - .clockevent_id = T0_BOT, - .clocksource_id = T0_TOP, +/* + * Bottom half of timer0 is used for clockevent, top half is used for + * clocksource. + */ +static const struct davinci_timer_cfg dm365_timer_cfg = { + .reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_128), + .irq = { + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)), + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)), + }, }; #define DM365_UART1_BASE (IO_PHYS + 0x106000) @@ -723,7 +730,6 @@ static const struct davinci_soc_info davinci_soc_info_dm365 = { .pinmux_base = DAVINCI_SYSTEM_MODULE_BASE, .pinmux_pins = dm365_pins, .pinmux_pins_num = ARRAY_SIZE(dm365_pins), - .timer_info = &dm365_timer_info, .emac_pdata = &dm365_emac_pdata, .sram_dma = 0x00010000, .sram_len = SZ_32K, @@ -771,6 +777,7 @@ void __init dm365_init_time(void) { void __iomem *pll1, *pll2, *psc; struct clk *clk; + int rv; clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM365_REF_FREQ); @@ -784,8 +791,13 @@ void __init dm365_init_time(void) dm365_psc_init(NULL, psc); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } - davinci_timer_init(clk); + rv = davinci_timer_register(clk, &dm365_timer_cfg); + WARN(rv, "Unable to register the timer: %d\n", rv); } void __init dm365_register_clocks(void) diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 1b9e9a6192ef..24988939ae46 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -27,7 +27,8 @@ #include <mach/cputype.h> #include <mach/mux.h> #include <mach/serial.h> -#include <mach/time.h> + +#include <clocksource/timer-davinci.h> #include "asp.h" #include "davinci.h" @@ -561,15 +562,15 @@ static struct davinci_id dm644x_ids[] = { }; /* - * T0_BOT: Timer 0, bottom: clockevent source for hrtimers - * T0_TOP: Timer 0, top : clocksource for generic timekeeping - * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) - * T1_TOP: Timer 1, top : <unused> + * Bottom half of timer0 is used for clockevent, top half is used for + * clocksource. */ -static struct davinci_timer_info dm644x_timer_info = { - .timers = davinci_timer_instance, - .clockevent_id = T0_BOT, - .clocksource_id = T0_TOP, +static const struct davinci_timer_cfg dm644x_timer_cfg = { + .reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K), + .irq = { + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)), + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)), + }, }; static struct plat_serial8250_port dm644x_serial0_platform_data[] = { @@ -647,7 +648,6 @@ static const struct davinci_soc_info davinci_soc_info_dm644x = { .pinmux_base = DAVINCI_SYSTEM_MODULE_BASE, .pinmux_pins = dm644x_pins, .pinmux_pins_num = ARRAY_SIZE(dm644x_pins), - .timer_info = &dm644x_timer_info, .emac_pdata = &dm644x_emac_pdata, .sram_dma = 0x00008000, .sram_len = SZ_16K, @@ -669,6 +669,7 @@ void __init dm644x_init_time(void) { void __iomem *pll1, *psc; struct clk *clk; + int rv; clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM644X_REF_FREQ); @@ -679,8 +680,13 @@ void __init dm644x_init_time(void) dm644x_psc_init(NULL, psc); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } - davinci_timer_init(clk); + rv = davinci_timer_register(clk, &dm644x_timer_cfg); + WARN(rv, "Unable to register the timer: %d\n", rv); } static struct resource dm644x_pll2_resources[] = { diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 62ca952fe161..4ffd028ed997 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -1,5 +1,5 @@ /* - * TI DaVinci DM644x chip specific setup + * TI DaVinci DM646x chip specific setup * * Author: Kevin Hilman, Deep Root Systems, LLC * @@ -28,7 +28,8 @@ #include <mach/cputype.h> #include <mach/mux.h> #include <mach/serial.h> -#include <mach/time.h> + +#include <clocksource/timer-davinci.h> #include "asp.h" #include "davinci.h" @@ -501,15 +502,15 @@ static struct davinci_id dm646x_ids[] = { }; /* - * T0_BOT: Timer 0, bottom: clockevent source for hrtimers - * T0_TOP: Timer 0, top : clocksource for generic timekeeping - * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) - * T1_TOP: Timer 1, top : <unused> + * Bottom half of timer0 is used for clockevent, top half is used for + * clocksource. */ -static struct davinci_timer_info dm646x_timer_info = { - .timers = davinci_timer_instance, - .clockevent_id = T0_BOT, - .clocksource_id = T0_TOP, +static const struct davinci_timer_cfg dm646x_timer_cfg = { + .reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K), + .irq = { + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)), + DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)), + }, }; static struct plat_serial8250_port dm646x_serial0_platform_data[] = { @@ -587,7 +588,6 @@ static const struct davinci_soc_info davinci_soc_info_dm646x = { .pinmux_base = DAVINCI_SYSTEM_MODULE_BASE, .pinmux_pins = dm646x_pins, .pinmux_pins_num = ARRAY_SIZE(dm646x_pins), - .timer_info = &dm646x_timer_info, .emac_pdata = &dm646x_emac_pdata, .sram_dma = 0x10010000, .sram_len = SZ_32K, @@ -652,6 +652,7 @@ void __init dm646x_init_time(unsigned long ref_clk_rate, { void __iomem *pll1, *psc; struct clk *clk; + int rv; clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, ref_clk_rate); clk_register_fixed_rate(NULL, "aux_clkin", NULL, 0, aux_clkin_rate); @@ -663,8 +664,13 @@ void __init dm646x_init_time(unsigned long ref_clk_rate, dm646x_psc_init(NULL, psc); clk = clk_get(NULL, "timer0"); + if (WARN_ON(IS_ERR(clk))) { + pr_err("Unable to get the timer clock\n"); + return; + } - davinci_timer_init(clk); + rv = davinci_timer_register(clk, &dm646x_timer_cfg); + WARN(rv, "Unable to register the timer: %d\n", rv); } static struct resource dm646x_pll2_resources[] = { diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 9526e5da0d33..139b83de011d 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -22,22 +22,6 @@ #define DAVINCI_INTC_START NR_IRQS #define DAVINCI_INTC_IRQ(_irqnum) (DAVINCI_INTC_START + (_irqnum)) -void davinci_timer_init(struct clk *clk); - -struct davinci_timer_instance { - u32 base; - u32 bottom_irq; - u32 top_irq; - unsigned long cmp_off; - unsigned int cmp_irq; -}; - -struct davinci_timer_info { - struct davinci_timer_instance *timers; - unsigned int clockevent_id; - unsigned int clocksource_id; -}; - struct davinci_gpio_controller; /* @@ -58,7 +42,6 @@ struct davinci_soc_info { u32 pinmux_base; const struct mux_config *pinmux_pins; unsigned long pinmux_pins_num; - struct davinci_timer_info *timer_info; int gpio_type; u32 gpio_base; unsigned gpio_num; diff --git a/arch/arm/mach-davinci/include/mach/time.h b/arch/arm/mach-davinci/include/mach/time.h deleted file mode 100644 index 1c971d8d8ba8..000000000000 --- a/arch/arm/mach-davinci/include/mach/time.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Local header file for DaVinci time code. - * - * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> - * - * 2007 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#ifndef __ARCH_ARM_MACH_DAVINCI_TIME_H -#define __ARCH_ARM_MACH_DAVINCI_TIME_H - -#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400) -#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800) -#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00) - -enum { - T0_BOT, - T0_TOP, - T1_BOT, - T1_TOP, - NUM_TIMERS -}; - -#define IS_TIMER1(id) (id & 0x2) -#define IS_TIMER0(id) (!IS_TIMER1(id)) -#define IS_TIMER_TOP(id) ((id & 0x1)) -#define IS_TIMER_BOT(id) (!IS_TIMER_TOP(id)) - -#define ID_TO_TIMER(id) (IS_TIMER1(id) != 0) - -extern struct davinci_timer_instance davinci_timer_instance[]; - -#endif /* __ARCH_ARM_MACH_DAVINCI_TIME_H */ diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c deleted file mode 100644 index 5a6de5368ab0..000000000000 --- a/arch/arm/mach-davinci/time.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * DaVinci timer subsystem - * - * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> - * - * 2007 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/clocksource.h> -#include <linux/clockchips.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/of.h> -#include <linux/platform_device.h> -#include <linux/sched_clock.h> - -#include <asm/mach/irq.h> -#include <asm/mach/time.h> - -#include <mach/cputype.h> -#include <mach/hardware.h> -#include <mach/time.h> - -static struct clock_event_device clockevent_davinci; -static unsigned int davinci_clock_tick_rate; - -/* - * This driver configures the 2 64-bit count-up timers as 4 independent - * 32-bit count-up timers used as follows: - */ - -enum { - TID_CLOCKEVENT, - TID_CLOCKSOURCE, -}; - -/* Timer register offsets */ -#define PID12 0x0 -#define TIM12 0x10 -#define TIM34 0x14 -#define PRD12 0x18 -#define PRD34 0x1c -#define TCR 0x20 -#define TGCR 0x24 -#define WDTCR 0x28 - -/* Offsets of the 8 compare registers */ -#define CMP12_0 0x60 -#define CMP12_1 0x64 -#define CMP12_2 0x68 -#define CMP12_3 0x6c -#define CMP12_4 0x70 -#define CMP12_5 0x74 -#define CMP12_6 0x78 -#define CMP12_7 0x7c - -/* Timer register bitfields */ -#define TCR_ENAMODE_DISABLE 0x0 -#define TCR_ENAMODE_ONESHOT 0x1 -#define TCR_ENAMODE_PERIODIC 0x2 -#define TCR_ENAMODE_MASK 0x3 - -#define TGCR_TIMMODE_SHIFT 2 -#define TGCR_TIMMODE_64BIT_GP 0x0 -#define TGCR_TIMMODE_32BIT_UNCHAINED 0x1 -#define TGCR_TIMMODE_64BIT_WDOG 0x2 -#define TGCR_TIMMODE_32BIT_CHAINED 0x3 - -#define TGCR_TIM12RS_SHIFT 0 -#define TGCR_TIM34RS_SHIFT 1 -#define TGCR_RESET 0x0 -#define TGCR_UNRESET 0x1 -#define TGCR_RESET_MASK 0x3 - -struct timer_s { - char *name; - unsigned int id; - unsigned long period; - unsigned long opts; - unsigned long flags; - void __iomem *base; - unsigned long tim_off; - unsigned long prd_off; - unsigned long enamode_shift; - struct irqaction irqaction; -}; -static struct timer_s timers[]; - -/* values for 'opts' field of struct timer_s */ -#define TIMER_OPTS_DISABLED 0x01 -#define TIMER_OPTS_ONESHOT 0x02 -#define TIMER_OPTS_PERIODIC 0x04 -#define TIMER_OPTS_STATE_MASK 0x07 - -#define TIMER_OPTS_USE_COMPARE 0x80000000 -#define USING_COMPARE(t) ((t)->opts & TIMER_OPTS_USE_COMPARE) - -static char *id_to_name[] = { - [T0_BOT] = "timer0_0", - [T0_TOP] = "timer0_1", - [T1_BOT] = "timer1_0", - [T1_TOP] = "timer1_1", -}; - -static int timer32_config(struct timer_s *t) -{ - u32 tcr; - struct davinci_soc_info *soc_info = &davinci_soc_info; - - if (USING_COMPARE(t)) { - struct davinci_timer_instance *dtip = - soc_info->timer_info->timers; - int event_timer = ID_TO_TIMER(timers[TID_CLOCKEVENT].id); - - /* - * Next interrupt should be the current time reg value plus - * the new period (using 32-bit unsigned addition/wrapping - * to 0 on overflow). This assumes that the clocksource - * is setup to count to 2^32-1 before wrapping around to 0. - */ - __raw_writel(__raw_readl(t->base + t->tim_off) + t->period, - t->base + dtip[event_timer].cmp_off); - } else { - tcr = __raw_readl(t->base + TCR); - - /* disable timer */ - tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift); - __raw_writel(tcr, t->base + TCR); - - /* reset counter to zero, set new period */ - __raw_writel(0, t->base + t->tim_off); - __raw_writel(t->period, t->base + t->prd_off); - - /* Set enable mode */ - if (t->opts & TIMER_OPTS_ONESHOT) - tcr |= TCR_ENAMODE_ONESHOT << t->enamode_shift; - else if (t->opts & TIMER_OPTS_PERIODIC) - tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift; - - __raw_writel(tcr, t->base + TCR); - } - return 0; -} - -static inline u32 timer32_read(struct timer_s *t) -{ - return __raw_readl(t->base + t->tim_off); -} - -static irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = &clockevent_davinci; - - evt->event_handler(evt); - return IRQ_HANDLED; -} - -/* called when 32-bit counter wraps */ -static irqreturn_t freerun_interrupt(int irq, void *dev_id) -{ - return IRQ_HANDLED; -} - -static struct timer_s timers[] = { - [TID_CLOCKEVENT] = { - .name = "clockevent", - .opts = TIMER_OPTS_DISABLED, - .irqaction = { - .flags = IRQF_TIMER, - .handler = timer_interrupt, - } - }, - [TID_CLOCKSOURCE] = { - .name = "free-run counter", - .period = ~0, - .opts = TIMER_OPTS_PERIODIC, - .irqaction = { - .flags = IRQF_TIMER, - .handler = freerun_interrupt, - } - }, -}; - -static void __init timer_init(void) -{ - struct davinci_soc_info *soc_info = &davinci_soc_info; - struct davinci_timer_instance *dtip = soc_info->timer_info->timers; - void __iomem *base[2]; - int i; - - /* Global init of each 64-bit timer as a whole */ - for(i=0; i<2; i++) { - u32 tgcr; - - base[i] = ioremap(dtip[i].base, SZ_4K); - if (WARN_ON(!base[i])) - continue; - - /* Disabled, Internal clock source */ - __raw_writel(0, base[i] + TCR); - - /* reset both timers, no pre-scaler for timer34 */ - tgcr = 0; - __raw_writel(tgcr, base[i] + TGCR); - - /* Set both timers to unchained 32-bit */ - tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT; - __raw_writel(tgcr, base[i] + TGCR); - - /* Unreset timers */ - tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) | - (TGCR_UNRESET << TGCR_TIM34RS_SHIFT); - __raw_writel(tgcr, base[i] + TGCR); - - /* Init both counters to zero */ - __raw_writel(0, base[i] + TIM12); - __raw_writel(0, base[i] + TIM34); - } - - /* Init of each timer as a 32-bit timer */ - for (i=0; i< ARRAY_SIZE(timers); i++) { - struct timer_s *t = &timers[i]; - int timer = ID_TO_TIMER(t->id); - u32 irq; - - t->base = base[timer]; - if (!t->base) - continue; - - if (IS_TIMER_BOT(t->id)) { - t->enamode_shift = 6; - t->tim_off = TIM12; - t->prd_off = PRD12; - irq = dtip[timer].bottom_irq; - } else { - t->enamode_shift = 22; - t->tim_off = TIM34; - t->prd_off = PRD34; - irq = dtip[timer].top_irq; - } - - /* Register interrupt */ - t->irqaction.name = t->name; - t->irqaction.dev_id = (void *)t; - - if (t->irqaction.handler != NULL) { - irq = USING_COMPARE(t) ? dtip[i].cmp_irq : irq; - setup_irq(irq, &t->irqaction); - } - } -} - -/* - * clocksource - */ -static u64 read_cycles(struct clocksource *cs) -{ - struct timer_s *t = &timers[TID_CLOCKSOURCE]; - - return (cycles_t)timer32_read(t); -} - -static struct clocksource clocksource_davinci = { - .rating = 300, - .read = read_cycles, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -/* - * Overwrite weak default sched_clock with something more precise - */ -static u64 notrace davinci_read_sched_clock(void) -{ - return timer32_read(&timers[TID_CLOCKSOURCE]); -} - -/* - * clockevent - */ -static int davinci_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - struct timer_s *t = &timers[TID_CLOCKEVENT]; - - t->period = cycles; - timer32_config(t); - return 0; -} - -static int davinci_shutdown(struct clock_event_device *evt) -{ - struct timer_s *t = &timers[TID_CLOCKEVENT]; - - t->opts &= ~TIMER_OPTS_STATE_MASK; - t->opts |= TIMER_OPTS_DISABLED; - return 0; -} - -static int davinci_set_oneshot(struct clock_event_device *evt) -{ - struct timer_s *t = &timers[TID_CLOCKEVENT]; - - t->opts &= ~TIMER_OPTS_STATE_MASK; - t->opts |= TIMER_OPTS_ONESHOT; - return 0; -} - -static int davinci_set_periodic(struct clock_event_device *evt) -{ - struct timer_s *t = &timers[TID_CLOCKEVENT]; - - t->period = davinci_clock_tick_rate / (HZ); - t->opts &= ~TIMER_OPTS_STATE_MASK; - t->opts |= TIMER_OPTS_PERIODIC; - timer32_config(t); - return 0; -} - -static struct clock_event_device clockevent_davinci = { - .features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = davinci_set_next_event, - .set_state_shutdown = davinci_shutdown, - .set_state_periodic = davinci_set_periodic, - .set_state_oneshot = davinci_set_oneshot, -}; - -void __init davinci_timer_init(struct clk *timer_clk) -{ - struct davinci_soc_info *soc_info = &davinci_soc_info; - unsigned int clockevent_id; - unsigned int clocksource_id; - int i; - - clockevent_id = soc_info->timer_info->clockevent_id; - clocksource_id = soc_info->timer_info->clocksource_id; - - timers[TID_CLOCKEVENT].id = clockevent_id; - timers[TID_CLOCKSOURCE].id = clocksource_id; - - /* - * If using same timer for both clock events & clocksource, - * a compare register must be used to generate an event interrupt. - * This is equivalent to a oneshot timer only (not periodic). - */ - if (clockevent_id == clocksource_id) { - struct davinci_timer_instance *dtip = - soc_info->timer_info->timers; - int event_timer = ID_TO_TIMER(clockevent_id); - - /* Only bottom timers can use compare regs */ - if (IS_TIMER_TOP(clockevent_id)) - pr_warn("%s: Invalid use of system timers. Results unpredictable.\n", - __func__); - else if ((dtip[event_timer].cmp_off == 0) - || (dtip[event_timer].cmp_irq == 0)) - pr_warn("%s: Invalid timer instance setup. Results unpredictable.\n", - __func__); - else { - timers[TID_CLOCKEVENT].opts |= TIMER_OPTS_USE_COMPARE; - clockevent_davinci.features = CLOCK_EVT_FEAT_ONESHOT; - } - } - - BUG_ON(IS_ERR(timer_clk)); - clk_prepare_enable(timer_clk); - - /* init timer hw */ - timer_init(); - - davinci_clock_tick_rate = clk_get_rate(timer_clk); - - /* setup clocksource */ - clocksource_davinci.name = id_to_name[clocksource_id]; - if (clocksource_register_hz(&clocksource_davinci, - davinci_clock_tick_rate)) - pr_err("%s: can't register clocksource!\n", - clocksource_davinci.name); - - sched_clock_register(davinci_read_sched_clock, 32, - davinci_clock_tick_rate); - - /* setup clockevent */ - clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id]; - - clockevent_davinci.cpumask = cpumask_of(0); - clockevents_config_and_register(&clockevent_davinci, - davinci_clock_tick_rate, 1, 0xfffffffe); - - for (i=0; i< ARRAY_SIZE(timers); i++) - timer32_config(&timers[i]); -} - -static int __init of_davinci_timer_init(struct device_node *np) -{ - struct clk *clk; - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - davinci_timer_init(clk); - - return 0; -} -TIMER_OF_DECLARE(davinci_timer, "ti,da830-timer", of_davinci_timer_init); |