"Das U-Boot" Source Tree
at master 106 lines 2.7 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * 64-bit Periodic Interval Timer driver 4 * 5 * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries 6 * 7 * Author: Claudiu Beznea <claudiu.beznea@microchip.com> 8 */ 9 10#include <clk.h> 11#include <dm.h> 12#include <timer.h> 13#include <asm/io.h> 14 15#define MCHP_PIT64B_CR 0x00 /* Control Register */ 16#define MCHP_PIT64B_CR_START BIT(0) 17#define MCHP_PIT64B_CR_SWRST BIT(8) 18#define MCHP_PIT64B_MR 0x04 /* Mode Register */ 19#define MCHP_PIT64B_MR_CONT BIT(0) 20#define MCHP_PIT64B_LSB_PR 0x08 /* LSB Period Register */ 21#define MCHP_PIT64B_MSB_PR 0x0C /* MSB Period Register */ 22#define MCHP_PIT64B_TLSBR 0x20 /* Timer LSB Register */ 23#define MCHP_PIT64B_TMSBR 0x24 /* Timer MSB Register */ 24 25struct mchp_pit64b_priv { 26 void __iomem *base; 27}; 28 29static u64 mchp_pit64b_get_count(struct udevice *dev) 30{ 31 struct mchp_pit64b_priv *priv = dev_get_priv(dev); 32 33 u32 lsb = readl(priv->base + MCHP_PIT64B_TLSBR); 34 u32 msb = readl(priv->base + MCHP_PIT64B_TMSBR); 35 36 return ((u64)msb << 32) | lsb; 37} 38 39static int mchp_pit64b_probe(struct udevice *dev) 40{ 41 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); 42 struct mchp_pit64b_priv *priv = dev_get_priv(dev); 43 struct clk clk; 44 ulong rate; 45 int ret; 46 47 priv->base = dev_read_addr_ptr(dev); 48 if (IS_ERR(priv->base)) 49 return PTR_ERR(priv->base); 50 51 ret = clk_get_by_index(dev, 0, &clk); 52 if (ret) 53 return ret; 54 55 ret = clk_enable(&clk); 56 if (ret) 57 return ret; 58 59 rate = clk_get_rate(&clk); 60 if (!rate) { 61 clk_disable(&clk); 62 return -ENOTSUPP; 63 } 64 65 /* Reset the timer in case it was used by previous bootloaders. */ 66 writel(MCHP_PIT64B_CR_SWRST, priv->base + MCHP_PIT64B_CR); 67 68 /* 69 * Use highest prescaller (for a peripheral clock running at 200MHz 70 * this will lead to the timer running at 12.5MHz) and continuous mode. 71 */ 72 writel((15 << 8) | MCHP_PIT64B_MR_CONT, priv->base + MCHP_PIT64B_MR); 73 uc_priv->clock_rate = rate / 16; 74 75 /* 76 * Simulate free running counter by setting max values to period 77 * registers. 78 */ 79 writel(~0UL, priv->base + MCHP_PIT64B_MSB_PR); 80 writel(~0UL, priv->base + MCHP_PIT64B_LSB_PR); 81 82 /* Start the timer. */ 83 writel(MCHP_PIT64B_CR_START, priv->base + MCHP_PIT64B_CR); 84 85 return 0; 86} 87 88static const struct timer_ops mchp_pit64b_ops = { 89 .get_count = mchp_pit64b_get_count, 90}; 91 92static const struct udevice_id mchp_pit64b_ids[] = { 93 { .compatible = "microchip,sam9x60-pit64b", }, 94 { .compatible = "microchip,sama7g5-pit64b", }, 95 { } 96}; 97 98U_BOOT_DRIVER(mchp_pit64b) = { 99 .name = "mchp-pit64b", 100 .id = UCLASS_TIMER, 101 .of_match = mchp_pit64b_ids, 102 .priv_auto = sizeof(struct mchp_pit64b_priv), 103 .probe = mchp_pit64b_probe, 104 .ops = &mchp_pit64b_ops, 105 .flags = DM_FLAG_PRE_RELOC, 106};