Skip to content
Snippets Groups Projects
ast_timer.c 2.13 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * Copyright 2016 Google Inc.
     *
     * SPDX-License-Identifier:	GPL-2.0+
     */
    
    #include <common.h>
    #include <dm.h>
    #include <errno.h>
    #include <timer.h>
    #include <asm/io.h>
    #include <asm/arch/timer.h>
    
    DECLARE_GLOBAL_DATA_PTR;
    
    #define AST_TICK_TIMER  1
    #define AST_TMC_RELOAD_VAL  0xffffffff
    
    struct ast_timer_priv {
    	struct ast_timer *regs;
    	struct ast_timer_counter *tmc;
    };
    
    static struct ast_timer_counter *ast_get_timer_counter(struct ast_timer *timer,
    						       int n)
    {
    	if (n > 3)
    		return &timer->timers2[n - 4];
    	else
    		return &timer->timers1[n - 1];
    }
    
    static int ast_timer_probe(struct udevice *dev)
    {
    	struct ast_timer_priv *priv = dev_get_priv(dev);
    	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
    
    	writel(AST_TMC_RELOAD_VAL, &priv->tmc->reload_val);
    
    	/*
    	 * Stop the timer. This will also load reload_val into
    	 * the status register.
    	 */
    	clrbits_le32(&priv->regs->ctrl1,
    		     AST_TMC_EN << AST_TMC_CTRL1_SHIFT(AST_TICK_TIMER));
    	/* Start the timer from the fixed 1MHz clock. */
    	setbits_le32(&priv->regs->ctrl1,
    		     (AST_TMC_EN | AST_TMC_1MHZ) <<
    		     AST_TMC_CTRL1_SHIFT(AST_TICK_TIMER));
    
    	uc_priv->clock_rate = AST_TMC_RATE;
    
    	return 0;
    }
    
    static int ast_timer_get_count(struct udevice *dev, u64 *count)
    {
    	struct ast_timer_priv *priv = dev_get_priv(dev);
    
    	*count = AST_TMC_RELOAD_VAL - readl(&priv->tmc->status);
    
    	return 0;
    }
    
    static int ast_timer_ofdata_to_platdata(struct udevice *dev)
    {
    	struct ast_timer_priv *priv = dev_get_priv(dev);
    
    	priv->regs = dev_get_addr_ptr(dev);
    	if (IS_ERR(priv->regs))
    		return PTR_ERR(priv->regs);
    
    	priv->tmc = ast_get_timer_counter(priv->regs, AST_TICK_TIMER);
    
    	return 0;
    }
    
    static const struct timer_ops ast_timer_ops = {
    	.get_count = ast_timer_get_count,
    };
    
    static const struct udevice_id ast_timer_ids[] = {
    	{ .compatible = "aspeed,ast2500-timer" },
    	{ .compatible = "aspeed,ast2400-timer" },
    	{ }
    };
    
    U_BOOT_DRIVER(ast_timer) = {
    	.name = "ast_timer",
    	.id = UCLASS_TIMER,
    	.of_match = ast_timer_ids,
    	.probe = ast_timer_probe,
    	.priv_auto_alloc_size = sizeof(struct ast_timer_priv),
    	.ofdata_to_platdata = ast_timer_ofdata_to_platdata,
    	.ops = &ast_timer_ops,
    	.flags = DM_FLAG_PRE_RELOC,
    };