Loading Documentation/kernel-parameters.txt +3 −1 Original line number Original line Diff line number Diff line Loading @@ -492,10 +492,12 @@ and is between 256 and 4096 characters. It is defined in the file Default: 64 Default: 64 hpet= [X86-32,HPET] option to control HPET usage hpet= [X86-32,HPET] option to control HPET usage Format: { enable (default) | disable | force } Format: { enable (default) | disable | force | verbose } disable: disable HPET and use PIT instead disable: disable HPET and use PIT instead force: allow force enabled of undocumented chips (ICH4, force: allow force enabled of undocumented chips (ICH4, VIA, nVidia) VIA, nVidia) verbose: show contents of HPET registers during setup com20020= [HW,NET] ARCnet - COM20020 chipset com20020= [HW,NET] ARCnet - COM20020 chipset Format: Format: Loading arch/x86/kernel/hpet.c +64 −16 Original line number Original line Diff line number Diff line Loading @@ -80,6 +80,7 @@ static inline void hpet_clear_mapping(void) */ */ static int boot_hpet_disable; static int boot_hpet_disable; int hpet_force_user; int hpet_force_user; static int hpet_verbose; static int __init hpet_setup(char *str) static int __init hpet_setup(char *str) { { Loading @@ -88,6 +89,8 @@ static int __init hpet_setup(char *str) boot_hpet_disable = 1; boot_hpet_disable = 1; if (!strncmp("force", str, 5)) if (!strncmp("force", str, 5)) hpet_force_user = 1; hpet_force_user = 1; if (!strncmp("verbose", str, 7)) hpet_verbose = 1; } } return 1; return 1; } } Loading Loading @@ -119,6 +122,43 @@ int is_hpet_enabled(void) } } EXPORT_SYMBOL_GPL(is_hpet_enabled); EXPORT_SYMBOL_GPL(is_hpet_enabled); static void _hpet_print_config(const char *function, int line) { u32 i, timers, l, h; printk(KERN_INFO "hpet: %s(%d):\n", function, line); l = hpet_readl(HPET_ID); h = hpet_readl(HPET_PERIOD); timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1; printk(KERN_INFO "hpet: ID: 0x%x, PERIOD: 0x%x\n", l, h); l = hpet_readl(HPET_CFG); h = hpet_readl(HPET_STATUS); printk(KERN_INFO "hpet: CFG: 0x%x, STATUS: 0x%x\n", l, h); l = hpet_readl(HPET_COUNTER); h = hpet_readl(HPET_COUNTER+4); printk(KERN_INFO "hpet: COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h); for (i = 0; i < timers; i++) { l = hpet_readl(HPET_Tn_CFG(i)); h = hpet_readl(HPET_Tn_CFG(i)+4); printk(KERN_INFO "hpet: T%d: CFG_l: 0x%x, CFG_h: 0x%x\n", i, l, h); l = hpet_readl(HPET_Tn_CMP(i)); h = hpet_readl(HPET_Tn_CMP(i)+4); printk(KERN_INFO "hpet: T%d: CMP_l: 0x%x, CMP_h: 0x%x\n", i, l, h); l = hpet_readl(HPET_Tn_ROUTE(i)); h = hpet_readl(HPET_Tn_ROUTE(i)+4); printk(KERN_INFO "hpet: T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n", i, l, h); } } #define hpet_print_config() \ do { \ if (hpet_verbose) \ _hpet_print_config(__FUNCTION__, __LINE__); \ } while (0) /* /* * When the hpet driver (/dev/hpet) is enabled, we need to reserve * When the hpet driver (/dev/hpet) is enabled, we need to reserve * timer 0 and timer 1 in case of RTC emulation. * timer 0 and timer 1 in case of RTC emulation. Loading Loading @@ -191,27 +231,37 @@ static struct clock_event_device hpet_clockevent = { .rating = 50, .rating = 50, }; }; static void hpet_start_counter(void) static void hpet_stop_counter(void) { { unsigned long cfg = hpet_readl(HPET_CFG); unsigned long cfg = hpet_readl(HPET_CFG); cfg &= ~HPET_CFG_ENABLE; cfg &= ~HPET_CFG_ENABLE; hpet_writel(cfg, HPET_CFG); hpet_writel(cfg, HPET_CFG); hpet_writel(0, HPET_COUNTER); hpet_writel(0, HPET_COUNTER); hpet_writel(0, HPET_COUNTER + 4); hpet_writel(0, HPET_COUNTER + 4); } static void hpet_start_counter(void) { unsigned long cfg = hpet_readl(HPET_CFG); cfg |= HPET_CFG_ENABLE; cfg |= HPET_CFG_ENABLE; hpet_writel(cfg, HPET_CFG); hpet_writel(cfg, HPET_CFG); } } static void hpet_restart_counter(void) { hpet_stop_counter(); hpet_start_counter(); } static void hpet_resume_device(void) static void hpet_resume_device(void) { { force_hpet_resume(); force_hpet_resume(); } } static void hpet_restart_counter(void) static void hpet_resume_counter(void) { { hpet_resume_device(); hpet_resume_device(); hpet_start_counter(); hpet_restart_counter(); } } static void hpet_enable_legacy_int(void) static void hpet_enable_legacy_int(void) Loading Loading @@ -259,29 +309,23 @@ static int hpet_setup_msi_irq(unsigned int irq); static void hpet_set_mode(enum clock_event_mode mode, static void hpet_set_mode(enum clock_event_mode mode, struct clock_event_device *evt, int timer) struct clock_event_device *evt, int timer) { { unsigned long cfg, cmp, now; unsigned long cfg; uint64_t delta; uint64_t delta; switch (mode) { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: case CLOCK_EVT_MODE_PERIODIC: hpet_stop_counter(); delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * evt->mult; delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * evt->mult; delta >>= evt->shift; delta >>= evt->shift; now = hpet_readl(HPET_COUNTER); cmp = now + (unsigned long) delta; cfg = hpet_readl(HPET_Tn_CFG(timer)); cfg = hpet_readl(HPET_Tn_CFG(timer)); /* Make sure we use edge triggered interrupts */ /* Make sure we use edge triggered interrupts */ cfg &= ~HPET_TN_LEVEL; cfg &= ~HPET_TN_LEVEL; cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | HPET_TN_32BIT; HPET_TN_SETVAL | HPET_TN_32BIT; hpet_writel(cfg, HPET_Tn_CFG(timer)); hpet_writel(cfg, HPET_Tn_CFG(timer)); /* * The first write after writing TN_SETVAL to the * config register sets the counter value, the second * write sets the period. */ hpet_writel(cmp, HPET_Tn_CMP(timer)); udelay(1); hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer)); hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer)); hpet_start_counter(); hpet_print_config(); break; break; case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_ONESHOT: Loading @@ -308,6 +352,7 @@ static void hpet_set_mode(enum clock_event_mode mode, irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu)); irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu)); enable_irq(hdev->irq); enable_irq(hdev->irq); } } hpet_print_config(); break; break; } } } } Loading Loading @@ -526,6 +571,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer) num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT); num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT); num_timers++; /* Value read out starts from 0 */ num_timers++; /* Value read out starts from 0 */ hpet_print_config(); hpet_devs = kzalloc(sizeof(struct hpet_dev) * num_timers, GFP_KERNEL); hpet_devs = kzalloc(sizeof(struct hpet_dev) * num_timers, GFP_KERNEL); if (!hpet_devs) if (!hpet_devs) Loading Loading @@ -695,7 +741,7 @@ static struct clocksource clocksource_hpet = { .mask = HPET_MASK, .mask = HPET_MASK, .shift = HPET_SHIFT, .shift = HPET_SHIFT, .flags = CLOCK_SOURCE_IS_CONTINUOUS, .flags = CLOCK_SOURCE_IS_CONTINUOUS, .resume = hpet_restart_counter, .resume = hpet_resume_counter, #ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64 .vread = vread_hpet, .vread = vread_hpet, #endif #endif Loading @@ -707,7 +753,7 @@ static int hpet_clocksource_register(void) cycle_t t1; cycle_t t1; /* Start the counter */ /* Start the counter */ hpet_start_counter(); hpet_restart_counter(); /* Verify whether hpet counter works */ /* Verify whether hpet counter works */ t1 = read_hpet(); t1 = read_hpet(); Loading Loading @@ -793,6 +839,7 @@ int __init hpet_enable(void) * information and the number of channels * information and the number of channels */ */ id = hpet_readl(HPET_ID); id = hpet_readl(HPET_ID); hpet_print_config(); #ifdef CONFIG_HPET_EMULATE_RTC #ifdef CONFIG_HPET_EMULATE_RTC /* /* Loading Loading @@ -845,6 +892,7 @@ static __init int hpet_late_init(void) return -ENODEV; return -ENODEV; hpet_reserve_platform_timers(hpet_readl(HPET_ID)); hpet_reserve_platform_timers(hpet_readl(HPET_ID)); hpet_print_config(); for_each_online_cpu(cpu) { for_each_online_cpu(cpu) { hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu); hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu); Loading Loading
Documentation/kernel-parameters.txt +3 −1 Original line number Original line Diff line number Diff line Loading @@ -492,10 +492,12 @@ and is between 256 and 4096 characters. It is defined in the file Default: 64 Default: 64 hpet= [X86-32,HPET] option to control HPET usage hpet= [X86-32,HPET] option to control HPET usage Format: { enable (default) | disable | force } Format: { enable (default) | disable | force | verbose } disable: disable HPET and use PIT instead disable: disable HPET and use PIT instead force: allow force enabled of undocumented chips (ICH4, force: allow force enabled of undocumented chips (ICH4, VIA, nVidia) VIA, nVidia) verbose: show contents of HPET registers during setup com20020= [HW,NET] ARCnet - COM20020 chipset com20020= [HW,NET] ARCnet - COM20020 chipset Format: Format: Loading
arch/x86/kernel/hpet.c +64 −16 Original line number Original line Diff line number Diff line Loading @@ -80,6 +80,7 @@ static inline void hpet_clear_mapping(void) */ */ static int boot_hpet_disable; static int boot_hpet_disable; int hpet_force_user; int hpet_force_user; static int hpet_verbose; static int __init hpet_setup(char *str) static int __init hpet_setup(char *str) { { Loading @@ -88,6 +89,8 @@ static int __init hpet_setup(char *str) boot_hpet_disable = 1; boot_hpet_disable = 1; if (!strncmp("force", str, 5)) if (!strncmp("force", str, 5)) hpet_force_user = 1; hpet_force_user = 1; if (!strncmp("verbose", str, 7)) hpet_verbose = 1; } } return 1; return 1; } } Loading Loading @@ -119,6 +122,43 @@ int is_hpet_enabled(void) } } EXPORT_SYMBOL_GPL(is_hpet_enabled); EXPORT_SYMBOL_GPL(is_hpet_enabled); static void _hpet_print_config(const char *function, int line) { u32 i, timers, l, h; printk(KERN_INFO "hpet: %s(%d):\n", function, line); l = hpet_readl(HPET_ID); h = hpet_readl(HPET_PERIOD); timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1; printk(KERN_INFO "hpet: ID: 0x%x, PERIOD: 0x%x\n", l, h); l = hpet_readl(HPET_CFG); h = hpet_readl(HPET_STATUS); printk(KERN_INFO "hpet: CFG: 0x%x, STATUS: 0x%x\n", l, h); l = hpet_readl(HPET_COUNTER); h = hpet_readl(HPET_COUNTER+4); printk(KERN_INFO "hpet: COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h); for (i = 0; i < timers; i++) { l = hpet_readl(HPET_Tn_CFG(i)); h = hpet_readl(HPET_Tn_CFG(i)+4); printk(KERN_INFO "hpet: T%d: CFG_l: 0x%x, CFG_h: 0x%x\n", i, l, h); l = hpet_readl(HPET_Tn_CMP(i)); h = hpet_readl(HPET_Tn_CMP(i)+4); printk(KERN_INFO "hpet: T%d: CMP_l: 0x%x, CMP_h: 0x%x\n", i, l, h); l = hpet_readl(HPET_Tn_ROUTE(i)); h = hpet_readl(HPET_Tn_ROUTE(i)+4); printk(KERN_INFO "hpet: T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n", i, l, h); } } #define hpet_print_config() \ do { \ if (hpet_verbose) \ _hpet_print_config(__FUNCTION__, __LINE__); \ } while (0) /* /* * When the hpet driver (/dev/hpet) is enabled, we need to reserve * When the hpet driver (/dev/hpet) is enabled, we need to reserve * timer 0 and timer 1 in case of RTC emulation. * timer 0 and timer 1 in case of RTC emulation. Loading Loading @@ -191,27 +231,37 @@ static struct clock_event_device hpet_clockevent = { .rating = 50, .rating = 50, }; }; static void hpet_start_counter(void) static void hpet_stop_counter(void) { { unsigned long cfg = hpet_readl(HPET_CFG); unsigned long cfg = hpet_readl(HPET_CFG); cfg &= ~HPET_CFG_ENABLE; cfg &= ~HPET_CFG_ENABLE; hpet_writel(cfg, HPET_CFG); hpet_writel(cfg, HPET_CFG); hpet_writel(0, HPET_COUNTER); hpet_writel(0, HPET_COUNTER); hpet_writel(0, HPET_COUNTER + 4); hpet_writel(0, HPET_COUNTER + 4); } static void hpet_start_counter(void) { unsigned long cfg = hpet_readl(HPET_CFG); cfg |= HPET_CFG_ENABLE; cfg |= HPET_CFG_ENABLE; hpet_writel(cfg, HPET_CFG); hpet_writel(cfg, HPET_CFG); } } static void hpet_restart_counter(void) { hpet_stop_counter(); hpet_start_counter(); } static void hpet_resume_device(void) static void hpet_resume_device(void) { { force_hpet_resume(); force_hpet_resume(); } } static void hpet_restart_counter(void) static void hpet_resume_counter(void) { { hpet_resume_device(); hpet_resume_device(); hpet_start_counter(); hpet_restart_counter(); } } static void hpet_enable_legacy_int(void) static void hpet_enable_legacy_int(void) Loading Loading @@ -259,29 +309,23 @@ static int hpet_setup_msi_irq(unsigned int irq); static void hpet_set_mode(enum clock_event_mode mode, static void hpet_set_mode(enum clock_event_mode mode, struct clock_event_device *evt, int timer) struct clock_event_device *evt, int timer) { { unsigned long cfg, cmp, now; unsigned long cfg; uint64_t delta; uint64_t delta; switch (mode) { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: case CLOCK_EVT_MODE_PERIODIC: hpet_stop_counter(); delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * evt->mult; delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * evt->mult; delta >>= evt->shift; delta >>= evt->shift; now = hpet_readl(HPET_COUNTER); cmp = now + (unsigned long) delta; cfg = hpet_readl(HPET_Tn_CFG(timer)); cfg = hpet_readl(HPET_Tn_CFG(timer)); /* Make sure we use edge triggered interrupts */ /* Make sure we use edge triggered interrupts */ cfg &= ~HPET_TN_LEVEL; cfg &= ~HPET_TN_LEVEL; cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | HPET_TN_32BIT; HPET_TN_SETVAL | HPET_TN_32BIT; hpet_writel(cfg, HPET_Tn_CFG(timer)); hpet_writel(cfg, HPET_Tn_CFG(timer)); /* * The first write after writing TN_SETVAL to the * config register sets the counter value, the second * write sets the period. */ hpet_writel(cmp, HPET_Tn_CMP(timer)); udelay(1); hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer)); hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer)); hpet_start_counter(); hpet_print_config(); break; break; case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_ONESHOT: Loading @@ -308,6 +352,7 @@ static void hpet_set_mode(enum clock_event_mode mode, irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu)); irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu)); enable_irq(hdev->irq); enable_irq(hdev->irq); } } hpet_print_config(); break; break; } } } } Loading Loading @@ -526,6 +571,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer) num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT); num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT); num_timers++; /* Value read out starts from 0 */ num_timers++; /* Value read out starts from 0 */ hpet_print_config(); hpet_devs = kzalloc(sizeof(struct hpet_dev) * num_timers, GFP_KERNEL); hpet_devs = kzalloc(sizeof(struct hpet_dev) * num_timers, GFP_KERNEL); if (!hpet_devs) if (!hpet_devs) Loading Loading @@ -695,7 +741,7 @@ static struct clocksource clocksource_hpet = { .mask = HPET_MASK, .mask = HPET_MASK, .shift = HPET_SHIFT, .shift = HPET_SHIFT, .flags = CLOCK_SOURCE_IS_CONTINUOUS, .flags = CLOCK_SOURCE_IS_CONTINUOUS, .resume = hpet_restart_counter, .resume = hpet_resume_counter, #ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64 .vread = vread_hpet, .vread = vread_hpet, #endif #endif Loading @@ -707,7 +753,7 @@ static int hpet_clocksource_register(void) cycle_t t1; cycle_t t1; /* Start the counter */ /* Start the counter */ hpet_start_counter(); hpet_restart_counter(); /* Verify whether hpet counter works */ /* Verify whether hpet counter works */ t1 = read_hpet(); t1 = read_hpet(); Loading Loading @@ -793,6 +839,7 @@ int __init hpet_enable(void) * information and the number of channels * information and the number of channels */ */ id = hpet_readl(HPET_ID); id = hpet_readl(HPET_ID); hpet_print_config(); #ifdef CONFIG_HPET_EMULATE_RTC #ifdef CONFIG_HPET_EMULATE_RTC /* /* Loading Loading @@ -845,6 +892,7 @@ static __init int hpet_late_init(void) return -ENODEV; return -ENODEV; hpet_reserve_platform_timers(hpet_readl(HPET_ID)); hpet_reserve_platform_timers(hpet_readl(HPET_ID)); hpet_print_config(); for_each_online_cpu(cpu) { for_each_online_cpu(cpu) { hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu); hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu); Loading