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