15184f4bfSNick Hawkins // SPDX-License-Identifier: GPL-2.0 25184f4bfSNick Hawkins /* Copyright (C) 2022 Hewlett-Packard Enterprise Development Company, L.P. */ 35184f4bfSNick Hawkins 45184f4bfSNick Hawkins #include <linux/clk.h> 55184f4bfSNick Hawkins #include <linux/clockchips.h> 65184f4bfSNick Hawkins #include <linux/clocksource.h> 75184f4bfSNick Hawkins #include <linux/interrupt.h> 85184f4bfSNick Hawkins #include <linux/of_address.h> 95184f4bfSNick Hawkins #include <linux/of_irq.h> 105184f4bfSNick Hawkins #include <linux/of_platform.h> 115184f4bfSNick Hawkins #include <linux/sched_clock.h> 125184f4bfSNick Hawkins 135184f4bfSNick Hawkins #define TIMER0_FREQ 1000000 145184f4bfSNick Hawkins #define GXP_TIMER_CNT_OFS 0x00 155184f4bfSNick Hawkins #define GXP_TIMESTAMP_OFS 0x08 165184f4bfSNick Hawkins #define GXP_TIMER_CTRL_OFS 0x14 175184f4bfSNick Hawkins 185184f4bfSNick Hawkins /* TCS Stands for Timer Control/Status: these are masks to be used in */ 195184f4bfSNick Hawkins /* the Timer Count Registers */ 205184f4bfSNick Hawkins #define MASK_TCS_ENABLE 0x01 215184f4bfSNick Hawkins #define MASK_TCS_PERIOD 0x02 225184f4bfSNick Hawkins #define MASK_TCS_RELOAD 0x04 235184f4bfSNick Hawkins #define MASK_TCS_TC 0x80 245184f4bfSNick Hawkins 255184f4bfSNick Hawkins struct gxp_timer { 265184f4bfSNick Hawkins void __iomem *counter; 275184f4bfSNick Hawkins void __iomem *control; 285184f4bfSNick Hawkins struct clock_event_device evt; 295184f4bfSNick Hawkins }; 305184f4bfSNick Hawkins 315184f4bfSNick Hawkins static struct gxp_timer *gxp_timer; 325184f4bfSNick Hawkins 335184f4bfSNick Hawkins static void __iomem *system_clock __ro_after_init; 345184f4bfSNick Hawkins 355184f4bfSNick Hawkins static inline struct gxp_timer *to_gxp_timer(struct clock_event_device *evt_dev) 365184f4bfSNick Hawkins { 375184f4bfSNick Hawkins return container_of(evt_dev, struct gxp_timer, evt); 385184f4bfSNick Hawkins } 395184f4bfSNick Hawkins 405184f4bfSNick Hawkins static u64 notrace gxp_sched_read(void) 415184f4bfSNick Hawkins { 425184f4bfSNick Hawkins return readl_relaxed(system_clock); 435184f4bfSNick Hawkins } 445184f4bfSNick Hawkins 455184f4bfSNick Hawkins static int gxp_time_set_next_event(unsigned long event, struct clock_event_device *evt_dev) 465184f4bfSNick Hawkins { 475184f4bfSNick Hawkins struct gxp_timer *timer = to_gxp_timer(evt_dev); 485184f4bfSNick Hawkins 495184f4bfSNick Hawkins /* Stop counting and disable interrupt before updating */ 505184f4bfSNick Hawkins writeb_relaxed(MASK_TCS_TC, timer->control); 515184f4bfSNick Hawkins writel_relaxed(event, timer->counter); 525184f4bfSNick Hawkins writeb_relaxed(MASK_TCS_TC | MASK_TCS_ENABLE, timer->control); 535184f4bfSNick Hawkins 545184f4bfSNick Hawkins return 0; 555184f4bfSNick Hawkins } 565184f4bfSNick Hawkins 575184f4bfSNick Hawkins static irqreturn_t gxp_timer_interrupt(int irq, void *dev_id) 585184f4bfSNick Hawkins { 595184f4bfSNick Hawkins struct gxp_timer *timer = (struct gxp_timer *)dev_id; 605184f4bfSNick Hawkins 615184f4bfSNick Hawkins if (!(readb_relaxed(timer->control) & MASK_TCS_TC)) 625184f4bfSNick Hawkins return IRQ_NONE; 635184f4bfSNick Hawkins 645184f4bfSNick Hawkins writeb_relaxed(MASK_TCS_TC, timer->control); 655184f4bfSNick Hawkins 665184f4bfSNick Hawkins timer->evt.event_handler(&timer->evt); 675184f4bfSNick Hawkins 685184f4bfSNick Hawkins return IRQ_HANDLED; 695184f4bfSNick Hawkins } 705184f4bfSNick Hawkins 715184f4bfSNick Hawkins static int __init gxp_timer_init(struct device_node *node) 725184f4bfSNick Hawkins { 735184f4bfSNick Hawkins void __iomem *base; 745184f4bfSNick Hawkins struct clk *clk; 755184f4bfSNick Hawkins u32 freq; 765184f4bfSNick Hawkins int ret, irq; 775184f4bfSNick Hawkins 785184f4bfSNick Hawkins gxp_timer = kzalloc(sizeof(*gxp_timer), GFP_KERNEL); 795184f4bfSNick Hawkins if (!gxp_timer) { 805184f4bfSNick Hawkins ret = -ENOMEM; 815184f4bfSNick Hawkins pr_err("Can't allocate gxp_timer"); 825184f4bfSNick Hawkins return ret; 835184f4bfSNick Hawkins } 845184f4bfSNick Hawkins 855184f4bfSNick Hawkins clk = of_clk_get(node, 0); 865184f4bfSNick Hawkins if (IS_ERR(clk)) { 875184f4bfSNick Hawkins ret = (int)PTR_ERR(clk); 885184f4bfSNick Hawkins pr_err("%pOFn clock not found: %d\n", node, ret); 895184f4bfSNick Hawkins goto err_free; 905184f4bfSNick Hawkins } 915184f4bfSNick Hawkins 925184f4bfSNick Hawkins ret = clk_prepare_enable(clk); 935184f4bfSNick Hawkins if (ret) { 945184f4bfSNick Hawkins pr_err("%pOFn clock enable failed: %d\n", node, ret); 955184f4bfSNick Hawkins goto err_clk_enable; 965184f4bfSNick Hawkins } 975184f4bfSNick Hawkins 985184f4bfSNick Hawkins base = of_iomap(node, 0); 995184f4bfSNick Hawkins if (!base) { 1005184f4bfSNick Hawkins ret = -ENXIO; 1015184f4bfSNick Hawkins pr_err("Can't map timer base registers"); 1025184f4bfSNick Hawkins goto err_iomap; 1035184f4bfSNick Hawkins } 1045184f4bfSNick Hawkins 1055184f4bfSNick Hawkins /* Set the offsets to the clock register and timer registers */ 1065184f4bfSNick Hawkins gxp_timer->counter = base + GXP_TIMER_CNT_OFS; 1075184f4bfSNick Hawkins gxp_timer->control = base + GXP_TIMER_CTRL_OFS; 1085184f4bfSNick Hawkins system_clock = base + GXP_TIMESTAMP_OFS; 1095184f4bfSNick Hawkins 1105184f4bfSNick Hawkins gxp_timer->evt.name = node->name; 1115184f4bfSNick Hawkins gxp_timer->evt.rating = 300; 1125184f4bfSNick Hawkins gxp_timer->evt.features = CLOCK_EVT_FEAT_ONESHOT; 1135184f4bfSNick Hawkins gxp_timer->evt.set_next_event = gxp_time_set_next_event; 1145184f4bfSNick Hawkins gxp_timer->evt.cpumask = cpumask_of(0); 1155184f4bfSNick Hawkins 1165184f4bfSNick Hawkins irq = irq_of_parse_and_map(node, 0); 1175184f4bfSNick Hawkins if (irq <= 0) { 1185184f4bfSNick Hawkins ret = -EINVAL; 1195184f4bfSNick Hawkins pr_err("GXP Timer Can't parse IRQ %d", irq); 1205184f4bfSNick Hawkins goto err_exit; 1215184f4bfSNick Hawkins } 1225184f4bfSNick Hawkins 1235184f4bfSNick Hawkins freq = clk_get_rate(clk); 1245184f4bfSNick Hawkins 1255184f4bfSNick Hawkins ret = clocksource_mmio_init(system_clock, node->name, freq, 1265184f4bfSNick Hawkins 300, 32, clocksource_mmio_readl_up); 1275184f4bfSNick Hawkins if (ret) { 1285184f4bfSNick Hawkins pr_err("%pOFn init clocksource failed: %d", node, ret); 1295184f4bfSNick Hawkins goto err_exit; 1305184f4bfSNick Hawkins } 1315184f4bfSNick Hawkins 1325184f4bfSNick Hawkins sched_clock_register(gxp_sched_read, 32, freq); 1335184f4bfSNick Hawkins 1345184f4bfSNick Hawkins irq = irq_of_parse_and_map(node, 0); 1355184f4bfSNick Hawkins if (irq <= 0) { 1365184f4bfSNick Hawkins ret = -EINVAL; 1375184f4bfSNick Hawkins pr_err("%pOFn Can't parse IRQ %d", node, irq); 1385184f4bfSNick Hawkins goto err_exit; 1395184f4bfSNick Hawkins } 1405184f4bfSNick Hawkins 1415184f4bfSNick Hawkins clockevents_config_and_register(&gxp_timer->evt, TIMER0_FREQ, 1425184f4bfSNick Hawkins 0xf, 0xffffffff); 1435184f4bfSNick Hawkins 1445184f4bfSNick Hawkins ret = request_irq(irq, gxp_timer_interrupt, IRQF_TIMER | IRQF_SHARED, 1455184f4bfSNick Hawkins node->name, gxp_timer); 1465184f4bfSNick Hawkins if (ret) { 1475184f4bfSNick Hawkins pr_err("%pOFn request_irq() failed: %d", node, ret); 1485184f4bfSNick Hawkins goto err_exit; 1495184f4bfSNick Hawkins } 1505184f4bfSNick Hawkins 1515184f4bfSNick Hawkins pr_debug("gxp: system timer (irq = %d)\n", irq); 1525184f4bfSNick Hawkins return 0; 1535184f4bfSNick Hawkins 1545184f4bfSNick Hawkins err_exit: 1555184f4bfSNick Hawkins iounmap(base); 1565184f4bfSNick Hawkins err_iomap: 1575184f4bfSNick Hawkins clk_disable_unprepare(clk); 1585184f4bfSNick Hawkins err_clk_enable: 1595184f4bfSNick Hawkins clk_put(clk); 1605184f4bfSNick Hawkins err_free: 1615184f4bfSNick Hawkins kfree(gxp_timer); 1625184f4bfSNick Hawkins return ret; 1635184f4bfSNick Hawkins } 1645184f4bfSNick Hawkins 1655184f4bfSNick Hawkins /* 1665184f4bfSNick Hawkins * This probe gets called after the timer is already up and running. This will create 1675184f4bfSNick Hawkins * the watchdog device as a child since the registers are shared. 1685184f4bfSNick Hawkins */ 1695184f4bfSNick Hawkins 1705184f4bfSNick Hawkins static int gxp_timer_probe(struct platform_device *pdev) 1715184f4bfSNick Hawkins { 1725184f4bfSNick Hawkins struct platform_device *gxp_watchdog_device; 1735184f4bfSNick Hawkins struct device *dev = &pdev->dev; 174*0e2c8e6dSLin Yujun int ret; 1755184f4bfSNick Hawkins 1765184f4bfSNick Hawkins if (!gxp_timer) { 1775184f4bfSNick Hawkins pr_err("Gxp Timer not initialized, cannot create watchdog"); 1785184f4bfSNick Hawkins return -ENOMEM; 1795184f4bfSNick Hawkins } 1805184f4bfSNick Hawkins 1815184f4bfSNick Hawkins gxp_watchdog_device = platform_device_alloc("gxp-wdt", -1); 1825184f4bfSNick Hawkins if (!gxp_watchdog_device) { 1835184f4bfSNick Hawkins pr_err("Timer failed to allocate gxp-wdt"); 1845184f4bfSNick Hawkins return -ENOMEM; 1855184f4bfSNick Hawkins } 1865184f4bfSNick Hawkins 1875184f4bfSNick Hawkins /* Pass the base address (counter) as platform data and nothing else */ 1885184f4bfSNick Hawkins gxp_watchdog_device->dev.platform_data = gxp_timer->counter; 1895184f4bfSNick Hawkins gxp_watchdog_device->dev.parent = dev; 1905184f4bfSNick Hawkins 191*0e2c8e6dSLin Yujun ret = platform_device_add(gxp_watchdog_device); 192*0e2c8e6dSLin Yujun if (ret) 193*0e2c8e6dSLin Yujun platform_device_put(gxp_watchdog_device); 194*0e2c8e6dSLin Yujun 195*0e2c8e6dSLin Yujun return ret; 1965184f4bfSNick Hawkins } 1975184f4bfSNick Hawkins 1985184f4bfSNick Hawkins static const struct of_device_id gxp_timer_of_match[] = { 1995184f4bfSNick Hawkins { .compatible = "hpe,gxp-timer", }, 2005184f4bfSNick Hawkins {}, 2015184f4bfSNick Hawkins }; 2025184f4bfSNick Hawkins 2035184f4bfSNick Hawkins static struct platform_driver gxp_timer_driver = { 2045184f4bfSNick Hawkins .probe = gxp_timer_probe, 2055184f4bfSNick Hawkins .driver = { 2065184f4bfSNick Hawkins .name = "gxp-timer", 2075184f4bfSNick Hawkins .of_match_table = gxp_timer_of_match, 2085184f4bfSNick Hawkins .suppress_bind_attrs = true, 2095184f4bfSNick Hawkins }, 2105184f4bfSNick Hawkins }; 2115184f4bfSNick Hawkins 2125184f4bfSNick Hawkins builtin_platform_driver(gxp_timer_driver); 2135184f4bfSNick Hawkins 2145184f4bfSNick Hawkins TIMER_OF_DECLARE(gxp, "hpe,gxp-timer", gxp_timer_init); 215