clk-nomadik.c revision ef6eb322ce574ba73658a677e83e5da3cfab301b
1ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/* 2ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * Nomadik clock implementation 3ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * Copyright (C) 2013 ST-Ericsson AB 4ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * License terms: GNU General Public License (GPL) version 2 5ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * Author: Linus Walleij <linus.walleij@linaro.org> 6ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij */ 7ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 8ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define pr_fmt(fmt) "Nomadik SRC clocks: " fmt 9ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 10ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/bitops.h> 114a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij#include <linux/clk.h> 124a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij#include <linux/clkdev.h> 134a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij#include <linux/err.h> 144a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij#include <linux/io.h> 154a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij#include <linux/clk-provider.h> 166e2b07a172b6ed98c7cdc301333b2d9f86c11880Linus Walleij#include <linux/of.h> 17ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/of_address.h> 18ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/debugfs.h> 19ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/seq_file.h> 20ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/spinlock.h> 21ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/reboot.h> 224a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij 234a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij/* 244a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij * The Nomadik clock tree is described in the STN8815A12 DB V4.2 254a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij * reference manual for the chip, page 94 ff. 26ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * Clock IDs are in the STn8815 Reference Manual table 3, page 27. 27ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij */ 28ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 29ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_CR 0x00U 30ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR 0x0CU 31ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR_XTALTIMEN BIT(20) 32ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR_SXTALDIS BIT(19) 33ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR_MXTALSTAT BIT(2) 34ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR_MXTALEN BIT(1) 35ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR_MXTALOVER BIT(0) 36ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR 0x10U 37ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR_PLLTIMEN BIT(29) 38ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR_PLL2EN BIT(28) 39ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR_PLL1STAT BIT(2) 40ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR_PLL1EN BIT(1) 41ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR_PLL1OVER BIT(0) 42ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLFR 0x14U 43ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKEN0 0x24U 44ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKDIS0 0x28U 45ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKENSR0 0x2CU 46ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKSR0 0x30U 47ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKEN1 0x34U 48ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKDIS1 0x38U 49ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKENSR1 0x3CU 50ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKSR1 0x40U 51ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 52ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/* Lock protecting the SRC_CR register */ 53ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic DEFINE_SPINLOCK(src_lock); 54ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/* Base address of the SRC */ 55ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void __iomem *src_base; 56ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 57ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/** 58ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * struct clk_pll1 - Nomadik PLL1 clock 59ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @hw: corresponding clock hardware entry 60ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @id: PLL instance: 1 or 2 61ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij */ 62ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstruct clk_pll { 63ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_hw hw; 64ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij int id; 65ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}; 66ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 67ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/** 68ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * struct clk_src - Nomadik src clock 69ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @hw: corresponding clock hardware entry 70ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @id: the clock ID 71ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @group1: true if the clock is in group1, else it is in group0 72ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @clkbit: bit 0...31 corresponding to the clock in each clock register 73ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij */ 74ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstruct clk_src { 75ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_hw hw; 76ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij int id; 77ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij bool group1; 78ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 clkbit; 79ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}; 80ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 81ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define to_pll(_hw) container_of(_hw, struct clk_pll, hw) 82ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define to_src(_hw) container_of(_hw, struct clk_src, hw) 83ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 84ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int pll_clk_enable(struct clk_hw *hw) 85ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 86ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_pll *pll = to_pll(hw); 87ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 val; 88ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 89ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij spin_lock(&src_lock); 90ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val = readl(src_base + SRC_PLLCR); 91ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (pll->id == 1) { 92ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (val & SRC_PLLCR_PLL1OVER) { 93ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val |= SRC_PLLCR_PLL1EN; 94ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij writel(val, src_base + SRC_PLLCR); 95ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 96ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } else if (pll->id == 2) { 97ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val |= SRC_PLLCR_PLL2EN; 98ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij writel(val, src_base + SRC_PLLCR); 99ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 100ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij spin_unlock(&src_lock); 101ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return 0; 102ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 103ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 104ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void pll_clk_disable(struct clk_hw *hw) 105ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 106ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_pll *pll = to_pll(hw); 107ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 val; 108ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 109ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij spin_lock(&src_lock); 110ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val = readl(src_base + SRC_PLLCR); 111ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (pll->id == 1) { 112ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (val & SRC_PLLCR_PLL1OVER) { 113ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val &= ~SRC_PLLCR_PLL1EN; 114ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij writel(val, src_base + SRC_PLLCR); 115ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 116ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } else if (pll->id == 2) { 117ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val &= ~SRC_PLLCR_PLL2EN; 118ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij writel(val, src_base + SRC_PLLCR); 119ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 120ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij spin_unlock(&src_lock); 121ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 122ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 123ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int pll_clk_is_enabled(struct clk_hw *hw) 124ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 125ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_pll *pll = to_pll(hw); 126ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 val; 127ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 128ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val = readl(src_base + SRC_PLLCR); 129ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (pll->id == 1) { 130ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (val & SRC_PLLCR_PLL1OVER) 131ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return !!(val & SRC_PLLCR_PLL1EN); 132ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } else if (pll->id == 2) { 133ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return !!(val & SRC_PLLCR_PLL2EN); 134ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 135ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return 1; 136ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 137ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 138ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic unsigned long pll_clk_recalc_rate(struct clk_hw *hw, 139ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij unsigned long parent_rate) 140ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 141ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_pll *pll = to_pll(hw); 142ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 val; 143ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 144ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val = readl(src_base + SRC_PLLFR); 145ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 146ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (pll->id == 1) { 147ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u8 mul; 148ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u8 div; 149ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 150ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij mul = (val >> 8) & 0x3FU; 151ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij mul += 2; 152ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij div = val & 0x07U; 153ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return (parent_rate * mul) >> div; 154ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 155ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 156ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (pll->id == 2) { 157ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u8 mul; 158ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 159ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij mul = (val >> 24) & 0x3FU; 160ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij mul += 2; 161ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return (parent_rate * mul); 162ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 163ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 164ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij /* Unknown PLL */ 165ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return 0; 166ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 167ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 168ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 169ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic const struct clk_ops pll_clk_ops = { 170ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .enable = pll_clk_enable, 171ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .disable = pll_clk_disable, 172ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .is_enabled = pll_clk_is_enabled, 173ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .recalc_rate = pll_clk_recalc_rate, 174ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}; 175ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 176ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic struct clk * __init 177ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijpll_clk_register(struct device *dev, const char *name, 178ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij const char *parent_name, u32 id) 179ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 180ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk *clk; 181ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_pll *pll; 182ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_init_data init; 183ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 184ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (id != 1 && id != 2) { 185ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_err("%s: the Nomadik has only PLL 1 & 2\n", __func__); 186ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return ERR_PTR(-EINVAL); 187ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 188ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 189ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pll = kzalloc(sizeof(*pll), GFP_KERNEL); 190ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (!pll) { 191ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_err("%s: could not allocate PLL clk\n", __func__); 192ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return ERR_PTR(-ENOMEM); 193ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 194ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 195ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij init.name = name; 196ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij init.ops = &pll_clk_ops; 197ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij init.parent_names = (parent_name ? &parent_name : NULL); 198ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij init.num_parents = (parent_name ? 1 : 0); 199ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pll->hw.init = &init; 200ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pll->id = id; 201ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 202ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_debug("register PLL1 clock \"%s\"\n", name); 203ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 204ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij clk = clk_register(dev, &pll->hw); 205ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (IS_ERR(clk)) 206ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij kfree(pll); 207ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 208ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return clk; 209ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 210ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 211ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/* 212ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * The Nomadik SRC clocks are gated, but not in the sense that 213ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * you read-modify-write a register. Instead there are separate 214ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * clock enable and clock disable registers. Writing a '1' bit in 215ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * the enable register for a certain clock ungates that clock without 216ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * affecting the other clocks. The disable register works the opposite 217ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * way. 2184a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij */ 2194a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij 220ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int src_clk_enable(struct clk_hw *hw) 221ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 222ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_src *sclk = to_src(hw); 223ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 enreg = sclk->group1 ? SRC_PCKEN1 : SRC_PCKEN0; 224ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0; 225ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 226ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij writel(sclk->clkbit, src_base + enreg); 227ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij /* spin until enabled */ 228ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij while (!(readl(src_base + sreg) & sclk->clkbit)) 229ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij cpu_relax(); 230ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return 0; 231ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 232ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 233ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void src_clk_disable(struct clk_hw *hw) 234ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 235ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_src *sclk = to_src(hw); 236ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 disreg = sclk->group1 ? SRC_PCKDIS1 : SRC_PCKDIS0; 237ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0; 238ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 239ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij writel(sclk->clkbit, src_base + disreg); 240ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij /* spin until disabled */ 241ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij while (readl(src_base + sreg) & sclk->clkbit) 242ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij cpu_relax(); 243ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 244ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 245ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int src_clk_is_enabled(struct clk_hw *hw) 246ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 247ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_src *sclk = to_src(hw); 248ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0; 249ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 val = readl(src_base + sreg); 250ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 251ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return !!(val & sclk->clkbit); 252ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 253ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 254ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic unsigned long 255ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijsrc_clk_recalc_rate(struct clk_hw *hw, 256ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij unsigned long parent_rate) 257ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 258ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return parent_rate; 259ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 260ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 261ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic const struct clk_ops src_clk_ops = { 262ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .enable = src_clk_enable, 263ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .disable = src_clk_disable, 264ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .is_enabled = src_clk_is_enabled, 265ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .recalc_rate = src_clk_recalc_rate, 266ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}; 267ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 268ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic struct clk * __init 269ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijsrc_clk_register(struct device *dev, const char *name, 270ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij const char *parent_name, u8 id) 271ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 272ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk *clk; 273ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_src *sclk; 274ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk_init_data init; 275ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 276ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij sclk = kzalloc(sizeof(*sclk), GFP_KERNEL); 277ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (!sclk) { 278ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_err("could not allocate SRC clock %s\n", 279ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij name); 280ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return ERR_PTR(-ENOMEM); 281ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 282ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij init.name = name; 283ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij init.ops = &src_clk_ops; 284ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij /* Do not force-disable the static SDRAM controller */ 285ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (id == 2) 286ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij init.flags = CLK_IGNORE_UNUSED; 287ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij else 288ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij init.flags = 0; 289ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij init.parent_names = (parent_name ? &parent_name : NULL); 290ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij init.num_parents = (parent_name ? 1 : 0); 291ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij sclk->hw.init = &init; 292ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij sclk->id = id; 293ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij sclk->group1 = (id > 31); 294ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij sclk->clkbit = BIT(id & 0x1f); 295ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 296ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_debug("register clock \"%s\" ID: %d group: %d bits: %08x\n", 297ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij name, id, sclk->group1, sclk->clkbit); 298ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 299ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij clk = clk_register(dev, &sclk->hw); 300ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (IS_ERR(clk)) 301ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij kfree(sclk); 302ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 303ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return clk; 304ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 305ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 306ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#ifdef CONFIG_DEBUG_FS 307ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 308ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic u32 src_pcksr0_boot; 309ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic u32 src_pcksr1_boot; 310ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 311ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic const char * const src_clk_names[] = { 312ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKDMA0 ", 313ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKSMC ", 314ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKSDRAM ", 315ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKDMA1 ", 316ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKCLCD ", 317ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKIRDA ", 318ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKSSP ", 319ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKUART0 ", 320ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKSDI ", 321ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKI2C0 ", 322ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKI2C1 ", 323ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKUART1 ", 324ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLMSP0 ", 325ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKUSB ", 326ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKDIF ", 327ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKSAA ", 328ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKSVA ", 329ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKHSI ", 330ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKXTI ", 331ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKUART2 ", 332ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKMSP1 ", 333ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKMSP2 ", 334ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKOWM ", 335ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKHPI ", 336ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKSKE ", 337ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKHSEM ", 338ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLK3D ", 339ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKHASH ", 340ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKCRYP ", 341ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKMSHC ", 342ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKUSBM ", 343ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HCLKRNG ", 344ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "RESERVED ", 345ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "RESERVED ", 346ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "RESERVED ", 347ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "RESERVED ", 348ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "CLDCLK ", 349ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "IRDACLK ", 350ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "SSPICLK ", 351ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "UART0CLK ", 352ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "SDICLK ", 353ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "I2C0CLK ", 354ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "I2C1CLK ", 355ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "UART1CLK ", 356ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "MSPCLK0 ", 357ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "USBCLK ", 358ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "DIFCLK ", 359ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "IPI2CCLK ", 360ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "IPBMCCLK ", 361ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HSICLKRX ", 362ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "HSICLKTX ", 363ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "UART2CLK ", 364ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "MSPCLK1 ", 365ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "MSPCLK2 ", 366ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "OWMCLK ", 367ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "RESERVED ", 368ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "SKECLK ", 369ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "RESERVED ", 370ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "3DCLK ", 371ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "PCLKMSP3 ", 372ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "MSPCLK3 ", 373ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "MSHCCLK ", 374ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "USBMCLK ", 375ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij "RNGCCLK ", 376ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}; 377ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 378ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int nomadik_src_clk_show(struct seq_file *s, void *what) 379ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 380ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij int i; 381ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 src_pcksr0 = readl(src_base + SRC_PCKSR0); 382ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 src_pcksr1 = readl(src_base + SRC_PCKSR1); 383ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 src_pckensr0 = readl(src_base + SRC_PCKENSR0); 384ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 src_pckensr1 = readl(src_base + SRC_PCKENSR1); 385ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 386ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij seq_printf(s, "Clock: Boot: Now: Request: ASKED:\n"); 387ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij for (i = 0; i < ARRAY_SIZE(src_clk_names); i++) { 388ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 pcksrb = (i < 0x20) ? src_pcksr0_boot : src_pcksr1_boot; 389ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 pcksr = (i < 0x20) ? src_pcksr0 : src_pcksr1; 390ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 pckreq = (i < 0x20) ? src_pckensr0 : src_pckensr1; 391ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 mask = BIT(i & 0x1f); 392ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 393ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij seq_printf(s, "%s %s %s %s\n", 394ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij src_clk_names[i], 395ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij (pcksrb & mask) ? "on " : "off", 396ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij (pcksr & mask) ? "on " : "off", 397ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij (pckreq & mask) ? "on " : "off"); 398ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 399ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return 0; 400ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 401ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 402ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int nomadik_src_clk_open(struct inode *inode, struct file *file) 403ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 404ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return single_open(file, nomadik_src_clk_show, NULL); 405ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 406ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 407ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic const struct file_operations nomadik_src_clk_debugfs_ops = { 408ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .open = nomadik_src_clk_open, 409ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .read = seq_read, 410ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .llseek = seq_lseek, 411ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .release = single_release, 412ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}; 413ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 414ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int __init nomadik_src_clk_init_debugfs(void) 415ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 416ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij src_pcksr0_boot = readl(src_base + SRC_PCKSR0); 417ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij src_pcksr1_boot = readl(src_base + SRC_PCKSR1); 418ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO, 419ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij NULL, NULL, &nomadik_src_clk_debugfs_ops); 420ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return 0; 421ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 422ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 423ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijmodule_init(nomadik_src_clk_init_debugfs); 424ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 425ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#endif 426ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 427ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void __init of_nomadik_pll_setup(struct device_node *np) 428ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 429ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk *clk = ERR_PTR(-EINVAL); 430ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij const char *clk_name = np->name; 431ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij const char *parent_name; 432ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 pll_id; 433ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 434ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (of_property_read_u32(np, "pll-id", &pll_id)) { 435ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_err("%s: PLL \"%s\" missing pll-id property\n", 436ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij __func__, clk_name); 437ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return; 438ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 439ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij parent_name = of_clk_get_parent_name(np, 0); 440ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij clk = pll_clk_register(NULL, clk_name, parent_name, pll_id); 441ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (!IS_ERR(clk)) 442ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij of_clk_add_provider(np, of_clk_src_simple_get, clk); 443ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 444ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 445ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void __init of_nomadik_hclk_setup(struct device_node *np) 446ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 447ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk *clk = ERR_PTR(-EINVAL); 448ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij const char *clk_name = np->name; 449ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij const char *parent_name; 450ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 451ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij parent_name = of_clk_get_parent_name(np, 0); 452ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij /* 453ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4. 454ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij */ 455ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij clk = clk_register_divider(NULL, clk_name, parent_name, 456ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 0, src_base + SRC_CR, 457ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 13, 2, 458ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, 459ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij &src_lock); 460ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (!IS_ERR(clk)) 461ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij of_clk_add_provider(np, of_clk_src_simple_get, clk); 462ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 463ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 464ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void __init of_nomadik_src_clk_setup(struct device_node *np) 465ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 466ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct clk *clk = ERR_PTR(-EINVAL); 467ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij const char *clk_name = np->name; 468ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij const char *parent_name; 469ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 clk_id; 470ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 471ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (of_property_read_u32(np, "clock-id", &clk_id)) { 472ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_err("%s: SRC clock \"%s\" missing clock-id property\n", 473ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij __func__, clk_name); 474ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return; 475ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 476ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij parent_name = of_clk_get_parent_name(np, 0); 477ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij clk = src_clk_register(NULL, clk_name, parent_name, clk_id); 478ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (!IS_ERR(clk)) 479ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij of_clk_add_provider(np, of_clk_src_simple_get, clk); 480ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 481ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 482ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic const __initconst struct of_device_id nomadik_src_match[] = { 483ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij { .compatible = "stericsson,nomadik-src" }, 4846e2b07a172b6ed98c7cdc301333b2d9f86c11880Linus Walleij { /* sentinel */ } 4856e2b07a172b6ed98c7cdc301333b2d9f86c11880Linus Walleij}; 4866e2b07a172b6ed98c7cdc301333b2d9f86c11880Linus Walleij 487ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic const __initconst struct of_device_id nomadik_src_clk_match[] = { 488ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij { 489ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .compatible = "fixed-clock", 490ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .data = of_fixed_clk_setup, 491ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij }, 492ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij { 493ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .compatible = "fixed-factor-clock", 494ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .data = of_fixed_factor_clk_setup, 495ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij }, 496ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij { 497ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .compatible = "st,nomadik-pll-clock", 498ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .data = of_nomadik_pll_setup, 499ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij }, 500ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij { 501ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .compatible = "st,nomadik-hclk-clock", 502ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .data = of_nomadik_hclk_setup, 503ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij }, 504ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij { 505ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .compatible = "st,nomadik-src-clock", 506ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .data = of_nomadik_src_clk_setup, 507ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij }, 508ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij { /* sentinel */ } 509ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}; 510ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 511ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int nomadik_clk_reboot_handler(struct notifier_block *this, 512ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij unsigned long code, 513ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij void *unused) 514ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{ 515ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 val; 516ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 517ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij /* The main chrystal need to be enabled for reboot to work */ 518ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val = readl(src_base + SRC_XTALCR); 519ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val &= ~SRC_XTALCR_MXTALOVER; 520ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val |= SRC_XTALCR_MXTALEN; 521ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_crit("force-enabling MXTALO\n"); 522ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij writel(val, src_base + SRC_XTALCR); 523ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return NOTIFY_OK; 524ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij} 525ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 526ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic struct notifier_block nomadik_clk_reboot_notifier = { 527ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij .notifier_call = nomadik_clk_reboot_handler, 528ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}; 529ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 5304a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleijvoid __init nomadik_clk_init(void) 5314a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij{ 532ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij struct device_node *np; 533ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij u32 val; 534ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 535ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij np = of_find_matching_node(NULL, nomadik_src_match); 536ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (!np) { 537ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_crit("no matching node for SRC, aborting clock init\n"); 538ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return; 539ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 540ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij src_base = of_iomap(np, 0); 541ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (!src_base) { 542ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_err("%s: must have src parent node with REGS (%s)\n", 543ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij __func__, np->name); 544ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij return; 545ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 546ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val = readl(src_base + SRC_XTALCR); 547ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_info("SXTALO is %s\n", 548ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij (val & SRC_XTALCR_SXTALDIS) ? "disabled" : "enabled"); 549ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_info("MXTAL is %s\n", 550ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij (val & SRC_XTALCR_MXTALSTAT) ? "enabled" : "disabled"); 551ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (of_property_read_bool(np, "disable-sxtalo")) { 552ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij /* The machine uses an external oscillator circuit */ 553ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val |= SRC_XTALCR_SXTALDIS; 554ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_info("disabling SXTALO\n"); 555ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 556ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij if (of_property_read_bool(np, "disable-mxtalo")) { 557ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij /* Disable this too: also run by external oscillator */ 558ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val |= SRC_XTALCR_MXTALOVER; 559ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij val &= ~SRC_XTALCR_MXTALEN; 560ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij pr_info("disabling MXTALO\n"); 561ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij } 562ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij writel(val, src_base + SRC_XTALCR); 563ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij register_reboot_notifier(&nomadik_clk_reboot_notifier); 564ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij 565ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij of_clk_init(nomadik_src_clk_match); 5664a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij} 567