132 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Clocksource using the Low Power Timer found in the Low Power Controller (LPC)4 *5 * Copyright (C) 2015 STMicroelectronics – All Rights Reserved6 *7 * Author(s): Francesco Virlinzi <francesco.virlinzi@st.com>8 * Ajit Pal Singh <ajitpal.singh@st.com>9 */10 11#include <linux/clk.h>12#include <linux/clocksource.h>13#include <linux/init.h>14#include <linux/of_address.h>15#include <linux/sched_clock.h>16#include <linux/slab.h>17 18#include <dt-bindings/mfd/st-lpc.h>19 20/* Low Power Timer */21#define LPC_LPT_LSB_OFF 0x40022#define LPC_LPT_MSB_OFF 0x40423#define LPC_LPT_START_OFF 0x40824 25static struct st_clksrc_ddata {26 struct clk *clk;27 void __iomem *base;28} ddata;29 30static void __init st_clksrc_reset(void)31{32 writel_relaxed(0, ddata.base + LPC_LPT_START_OFF);33 writel_relaxed(0, ddata.base + LPC_LPT_MSB_OFF);34 writel_relaxed(0, ddata.base + LPC_LPT_LSB_OFF);35 writel_relaxed(1, ddata.base + LPC_LPT_START_OFF);36}37 38static u64 notrace st_clksrc_sched_clock_read(void)39{40 return (u64)readl_relaxed(ddata.base + LPC_LPT_LSB_OFF);41}42 43static int __init st_clksrc_init(void)44{45 unsigned long rate;46 int ret;47 48 st_clksrc_reset();49 50 rate = clk_get_rate(ddata.clk);51 52 sched_clock_register(st_clksrc_sched_clock_read, 32, rate);53 54 ret = clocksource_mmio_init(ddata.base + LPC_LPT_LSB_OFF,55 "clksrc-st-lpc", rate, 300, 32,56 clocksource_mmio_readl_up);57 if (ret) {58 pr_err("clksrc-st-lpc: Failed to register clocksource\n");59 return ret;60 }61 62 return 0;63}64 65static int __init st_clksrc_setup_clk(struct device_node *np)66{67 struct clk *clk;68 69 clk = of_clk_get(np, 0);70 if (IS_ERR(clk)) {71 pr_err("clksrc-st-lpc: Failed to get LPC clock\n");72 return PTR_ERR(clk);73 }74 75 if (clk_prepare_enable(clk)) {76 pr_err("clksrc-st-lpc: Failed to enable LPC clock\n");77 return -EINVAL;78 }79 80 if (!clk_get_rate(clk)) {81 pr_err("clksrc-st-lpc: Failed to get LPC clock rate\n");82 clk_disable_unprepare(clk);83 return -EINVAL;84 }85 86 ddata.clk = clk;87 88 return 0;89}90 91static int __init st_clksrc_of_register(struct device_node *np)92{93 int ret;94 uint32_t mode;95 96 ret = of_property_read_u32(np, "st,lpc-mode", &mode);97 if (ret) {98 pr_err("clksrc-st-lpc: An LPC mode must be provided\n");99 return ret;100 }101 102 /* LPC can either run as a Clocksource or in RTC or WDT mode */103 if (mode != ST_LPC_MODE_CLKSRC)104 return 0;105 106 ddata.base = of_iomap(np, 0);107 if (!ddata.base) {108 pr_err("clksrc-st-lpc: Unable to map iomem\n");109 return -ENXIO;110 }111 112 ret = st_clksrc_setup_clk(np);113 if (ret) {114 iounmap(ddata.base);115 return ret;116 }117 118 ret = st_clksrc_init();119 if (ret) {120 clk_disable_unprepare(ddata.clk);121 clk_put(ddata.clk);122 iounmap(ddata.base);123 return ret;124 }125 126 pr_info("clksrc-st-lpc: clocksource initialised - running @ %luHz\n",127 clk_get_rate(ddata.clk));128 129 return ret;130}131TIMER_OF_DECLARE(ddata, "st,stih407-lpc", st_clksrc_of_register);132