linux/drivers/clk/ti/clkt_iclk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * OMAP2/3 interface clock control
   4 *
   5 * Copyright (C) 2011 Nokia Corporation
   6 * Paul Walmsley
   7 */
   8#undef DEBUG
   9
  10#include <linux/kernel.h>
  11#include <linux/clk-provider.h>
  12#include <linux/io.h>
  13#include <linux/clk/ti.h>
  14
  15#include "clock.h"
  16
  17/* Register offsets */
  18#define OMAP24XX_CM_FCLKEN2             0x04
  19#define CM_AUTOIDLE                     0x30
  20#define CM_ICLKEN                       0x10
  21#define CM_IDLEST                       0x20
  22
  23#define OMAP24XX_CM_IDLEST_VAL          0
  24
  25/* Private functions */
  26
  27/* XXX */
  28void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
  29{
  30        u32 v;
  31        struct clk_omap_reg r;
  32
  33        memcpy(&r, &clk->enable_reg, sizeof(r));
  34        r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN);
  35
  36        v = ti_clk_ll_ops->clk_readl(&r);
  37        v |= (1 << clk->enable_bit);
  38        ti_clk_ll_ops->clk_writel(v, &r);
  39}
  40
  41/* XXX */
  42void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
  43{
  44        u32 v;
  45        struct clk_omap_reg r;
  46
  47        memcpy(&r, &clk->enable_reg, sizeof(r));
  48
  49        r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN);
  50
  51        v = ti_clk_ll_ops->clk_readl(&r);
  52        v &= ~(1 << clk->enable_bit);
  53        ti_clk_ll_ops->clk_writel(v, &r);
  54}
  55
  56/**
  57 * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
  58 * @clk: struct clk * being enabled
  59 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  60 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  61 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
  62 *
  63 * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
  64 * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE.  This custom function
  65 * passes back the correct CM_IDLEST register address for I2CHS
  66 * modules.  No return value.
  67 */
  68static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
  69                                           struct clk_omap_reg *idlest_reg,
  70                                           u8 *idlest_bit,
  71                                           u8 *idlest_val)
  72{
  73        memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
  74        idlest_reg->offset ^= (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST);
  75        *idlest_bit = clk->enable_bit;
  76        *idlest_val = OMAP24XX_CM_IDLEST_VAL;
  77}
  78
  79/* Public data */
  80
  81const struct clk_hw_omap_ops clkhwops_iclk = {
  82        .allow_idle     = omap2_clkt_iclk_allow_idle,
  83        .deny_idle      = omap2_clkt_iclk_deny_idle,
  84};
  85
  86const struct clk_hw_omap_ops clkhwops_iclk_wait = {
  87        .allow_idle     = omap2_clkt_iclk_allow_idle,
  88        .deny_idle      = omap2_clkt_iclk_deny_idle,
  89        .find_idlest    = omap2_clk_dflt_find_idlest,
  90        .find_companion = omap2_clk_dflt_find_companion,
  91};
  92
  93/* 2430 I2CHS has non-standard IDLEST register */
  94const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
  95        .find_idlest    = omap2430_clk_i2chs_find_idlest,
  96        .find_companion = omap2_clk_dflt_find_companion,
  97};
  98