linux/drivers/clk/ti/mux.c
<<
>>
Prefs
   1/*
   2 * TI Multiplexer Clock
   3 *
   4 * Copyright (C) 2013 Texas Instruments, Inc.
   5 *
   6 * Tero Kristo <t-kristo@ti.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 *
  12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  13 * kind, whether express or implied; without even the implied warranty
  14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 */
  17
  18#include <linux/clk-provider.h>
  19#include <linux/slab.h>
  20#include <linux/err.h>
  21#include <linux/of.h>
  22#include <linux/of_address.h>
  23#include <linux/clk/ti.h>
  24#include "clock.h"
  25
  26#undef pr_fmt
  27#define pr_fmt(fmt) "%s: " fmt, __func__
  28
  29static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
  30{
  31        struct clk_omap_mux *mux = to_clk_omap_mux(hw);
  32        int num_parents = clk_hw_get_num_parents(hw);
  33        u32 val;
  34
  35        /*
  36         * FIXME need a mux-specific flag to determine if val is bitwise or
  37         * numeric. e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges
  38         * from 0x1 to 0x7 (index starts at one)
  39         * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
  40         * val = 0x4 really means "bit 2, index starts at bit 0"
  41         */
  42        val = ti_clk_ll_ops->clk_readl(&mux->reg) >> mux->shift;
  43        val &= mux->mask;
  44
  45        if (mux->table) {
  46                int i;
  47
  48                for (i = 0; i < num_parents; i++)
  49                        if (mux->table[i] == val)
  50                                return i;
  51                return -EINVAL;
  52        }
  53
  54        if (val && (mux->flags & CLK_MUX_INDEX_BIT))
  55                val = ffs(val) - 1;
  56
  57        if (val && (mux->flags & CLK_MUX_INDEX_ONE))
  58                val--;
  59
  60        if (val >= num_parents)
  61                return -EINVAL;
  62
  63        return val;
  64}
  65
  66static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
  67{
  68        struct clk_omap_mux *mux = to_clk_omap_mux(hw);
  69        u32 val;
  70
  71        if (mux->table) {
  72                index = mux->table[index];
  73        } else {
  74                if (mux->flags & CLK_MUX_INDEX_BIT)
  75                        index = (1 << ffs(index));
  76
  77                if (mux->flags & CLK_MUX_INDEX_ONE)
  78                        index++;
  79        }
  80
  81        if (mux->flags & CLK_MUX_HIWORD_MASK) {
  82                val = mux->mask << (mux->shift + 16);
  83        } else {
  84                val = ti_clk_ll_ops->clk_readl(&mux->reg);
  85                val &= ~(mux->mask << mux->shift);
  86        }
  87        val |= index << mux->shift;
  88        ti_clk_ll_ops->clk_writel(val, &mux->reg);
  89        ti_clk_latch(&mux->reg, mux->latch);
  90
  91        return 0;
  92}
  93
  94const struct clk_ops ti_clk_mux_ops = {
  95        .get_parent = ti_clk_mux_get_parent,
  96        .set_parent = ti_clk_mux_set_parent,
  97        .determine_rate = __clk_mux_determine_rate,
  98};
  99
 100static struct clk *_register_mux(struct device *dev, const char *name,
 101                                 const char * const *parent_names,
 102                                 u8 num_parents, unsigned long flags,
 103                                 struct clk_omap_reg *reg, u8 shift, u32 mask,
 104                                 s8 latch, u8 clk_mux_flags, u32 *table)
 105{
 106        struct clk_omap_mux *mux;
 107        struct clk *clk;
 108        struct clk_init_data init;
 109
 110        /* allocate the mux */
 111        mux = kzalloc(sizeof(*mux), GFP_KERNEL);
 112        if (!mux)
 113                return ERR_PTR(-ENOMEM);
 114
 115        init.name = name;
 116        init.ops = &ti_clk_mux_ops;
 117        init.flags = flags | CLK_IS_BASIC;
 118        init.parent_names = parent_names;
 119        init.num_parents = num_parents;
 120
 121        /* struct clk_mux assignments */
 122        memcpy(&mux->reg, reg, sizeof(*reg));
 123        mux->shift = shift;
 124        mux->mask = mask;
 125        mux->latch = latch;
 126        mux->flags = clk_mux_flags;
 127        mux->table = table;
 128        mux->hw.init = &init;
 129
 130        clk = ti_clk_register(dev, &mux->hw, name);
 131
 132        if (IS_ERR(clk))
 133                kfree(mux);
 134
 135        return clk;
 136}
 137
 138struct clk *ti_clk_register_mux(struct ti_clk *setup)
 139{
 140        struct ti_clk_mux *mux;
 141        u32 flags;
 142        u8 mux_flags = 0;
 143        struct clk_omap_reg reg;
 144        u32 mask;
 145
 146        mux = setup->data;
 147        flags = CLK_SET_RATE_NO_REPARENT;
 148
 149        mask = mux->num_parents;
 150        if (!(mux->flags & CLKF_INDEX_STARTS_AT_ONE))
 151                mask--;
 152
 153        mask = (1 << fls(mask)) - 1;
 154        reg.index = mux->module;
 155        reg.offset = mux->reg;
 156        reg.ptr = NULL;
 157
 158        if (mux->flags & CLKF_INDEX_STARTS_AT_ONE)
 159                mux_flags |= CLK_MUX_INDEX_ONE;
 160
 161        if (mux->flags & CLKF_SET_RATE_PARENT)
 162                flags |= CLK_SET_RATE_PARENT;
 163
 164        return _register_mux(NULL, setup->name, mux->parents, mux->num_parents,
 165                             flags, &reg, mux->bit_shift, mask, -EINVAL,
 166                             mux_flags, NULL);
 167}
 168
 169/**
 170 * of_mux_clk_setup - Setup function for simple mux rate clock
 171 * @node: DT node for the clock
 172 *
 173 * Sets up a basic clock multiplexer.
 174 */
 175static void of_mux_clk_setup(struct device_node *node)
 176{
 177        struct clk *clk;
 178        struct clk_omap_reg reg;
 179        unsigned int num_parents;
 180        const char **parent_names;
 181        u8 clk_mux_flags = 0;
 182        u32 mask = 0;
 183        u32 shift = 0;
 184        s32 latch = -EINVAL;
 185        u32 flags = CLK_SET_RATE_NO_REPARENT;
 186
 187        num_parents = of_clk_get_parent_count(node);
 188        if (num_parents < 2) {
 189                pr_err("mux-clock %s must have parents\n", node->name);
 190                return;
 191        }
 192        parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
 193        if (!parent_names)
 194                goto cleanup;
 195
 196        of_clk_parent_fill(node, parent_names, num_parents);
 197
 198        if (ti_clk_get_reg_addr(node, 0, &reg))
 199                goto cleanup;
 200
 201        of_property_read_u32(node, "ti,bit-shift", &shift);
 202
 203        of_property_read_u32(node, "ti,latch-bit", &latch);
 204
 205        if (of_property_read_bool(node, "ti,index-starts-at-one"))
 206                clk_mux_flags |= CLK_MUX_INDEX_ONE;
 207
 208        if (of_property_read_bool(node, "ti,set-rate-parent"))
 209                flags |= CLK_SET_RATE_PARENT;
 210
 211        /* Generate bit-mask based on parent info */
 212        mask = num_parents;
 213        if (!(clk_mux_flags & CLK_MUX_INDEX_ONE))
 214                mask--;
 215
 216        mask = (1 << fls(mask)) - 1;
 217
 218        clk = _register_mux(NULL, node->name, parent_names, num_parents,
 219                            flags, &reg, shift, mask, latch, clk_mux_flags,
 220                            NULL);
 221
 222        if (!IS_ERR(clk))
 223                of_clk_add_provider(node, of_clk_src_simple_get, clk);
 224
 225cleanup:
 226        kfree(parent_names);
 227}
 228CLK_OF_DECLARE(mux_clk, "ti,mux-clock", of_mux_clk_setup);
 229
 230struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup)
 231{
 232        struct clk_omap_mux *mux;
 233        int num_parents;
 234
 235        if (!setup)
 236                return NULL;
 237
 238        mux = kzalloc(sizeof(*mux), GFP_KERNEL);
 239        if (!mux)
 240                return ERR_PTR(-ENOMEM);
 241
 242        mux->shift = setup->bit_shift;
 243        mux->latch = -EINVAL;
 244
 245        mux->reg.index = setup->module;
 246        mux->reg.offset = setup->reg;
 247
 248        if (setup->flags & CLKF_INDEX_STARTS_AT_ONE)
 249                mux->flags |= CLK_MUX_INDEX_ONE;
 250
 251        num_parents = setup->num_parents;
 252
 253        mux->mask = num_parents - 1;
 254        mux->mask = (1 << fls(mux->mask)) - 1;
 255
 256        return &mux->hw;
 257}
 258
 259static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
 260{
 261        struct clk_omap_mux *mux;
 262        unsigned int num_parents;
 263        u32 val;
 264
 265        mux = kzalloc(sizeof(*mux), GFP_KERNEL);
 266        if (!mux)
 267                return;
 268
 269        if (ti_clk_get_reg_addr(node, 0, &mux->reg))
 270                goto cleanup;
 271
 272        if (!of_property_read_u32(node, "ti,bit-shift", &val))
 273                mux->shift = val;
 274
 275        if (of_property_read_bool(node, "ti,index-starts-at-one"))
 276                mux->flags |= CLK_MUX_INDEX_ONE;
 277
 278        num_parents = of_clk_get_parent_count(node);
 279
 280        if (num_parents < 2) {
 281                pr_err("%s must have parents\n", node->name);
 282                goto cleanup;
 283        }
 284
 285        mux->mask = num_parents - 1;
 286        mux->mask = (1 << fls(mux->mask)) - 1;
 287
 288        if (!ti_clk_add_component(node, &mux->hw, CLK_COMPONENT_TYPE_MUX))
 289                return;
 290
 291cleanup:
 292        kfree(mux);
 293}
 294CLK_OF_DECLARE(ti_composite_mux_clk_setup, "ti,composite-mux-clock",
 295               of_ti_composite_mux_clk_setup);
 296