162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * OMAP2/3 interface clock control 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2011 Nokia Corporation 662306a36Sopenharmony_ci * Paul Walmsley 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#undef DEBUG 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/clk-provider.h> 1262306a36Sopenharmony_ci#include <linux/io.h> 1362306a36Sopenharmony_ci#include <linux/clk/ti.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "clock.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* Register offsets */ 1862306a36Sopenharmony_ci#define OMAP24XX_CM_FCLKEN2 0x04 1962306a36Sopenharmony_ci#define CM_AUTOIDLE 0x30 2062306a36Sopenharmony_ci#define CM_ICLKEN 0x10 2162306a36Sopenharmony_ci#define CM_IDLEST 0x20 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define OMAP24XX_CM_IDLEST_VAL 0 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* Private functions */ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* XXX */ 2862306a36Sopenharmony_civoid omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci u32 v; 3162306a36Sopenharmony_ci struct clk_omap_reg r; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci memcpy(&r, &clk->enable_reg, sizeof(r)); 3462306a36Sopenharmony_ci r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci v = ti_clk_ll_ops->clk_readl(&r); 3762306a36Sopenharmony_ci v |= (1 << clk->enable_bit); 3862306a36Sopenharmony_ci ti_clk_ll_ops->clk_writel(v, &r); 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* XXX */ 4262306a36Sopenharmony_civoid omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci u32 v; 4562306a36Sopenharmony_ci struct clk_omap_reg r; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci memcpy(&r, &clk->enable_reg, sizeof(r)); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci v = ti_clk_ll_ops->clk_readl(&r); 5262306a36Sopenharmony_ci v &= ~(1 << clk->enable_bit); 5362306a36Sopenharmony_ci ti_clk_ll_ops->clk_writel(v, &r); 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/** 5762306a36Sopenharmony_ci * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS 5862306a36Sopenharmony_ci * @clk: struct clk * being enabled 5962306a36Sopenharmony_ci * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into 6062306a36Sopenharmony_ci * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into 6162306a36Sopenharmony_ci * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator 6262306a36Sopenharmony_ci * 6362306a36Sopenharmony_ci * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the 6462306a36Sopenharmony_ci * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE. This custom function 6562306a36Sopenharmony_ci * passes back the correct CM_IDLEST register address for I2CHS 6662306a36Sopenharmony_ci * modules. No return value. 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_cistatic void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk, 6962306a36Sopenharmony_ci struct clk_omap_reg *idlest_reg, 7062306a36Sopenharmony_ci u8 *idlest_bit, 7162306a36Sopenharmony_ci u8 *idlest_val) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); 7462306a36Sopenharmony_ci idlest_reg->offset ^= (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST); 7562306a36Sopenharmony_ci *idlest_bit = clk->enable_bit; 7662306a36Sopenharmony_ci *idlest_val = OMAP24XX_CM_IDLEST_VAL; 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* Public data */ 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_iclk = { 8262306a36Sopenharmony_ci .allow_idle = omap2_clkt_iclk_allow_idle, 8362306a36Sopenharmony_ci .deny_idle = omap2_clkt_iclk_deny_idle, 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_iclk_wait = { 8762306a36Sopenharmony_ci .allow_idle = omap2_clkt_iclk_allow_idle, 8862306a36Sopenharmony_ci .deny_idle = omap2_clkt_iclk_deny_idle, 8962306a36Sopenharmony_ci .find_idlest = omap2_clk_dflt_find_idlest, 9062306a36Sopenharmony_ci .find_companion = omap2_clk_dflt_find_companion, 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* 2430 I2CHS has non-standard IDLEST register */ 9462306a36Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = { 9562306a36Sopenharmony_ci .find_idlest = omap2430_clk_i2chs_find_idlest, 9662306a36Sopenharmony_ci .find_companion = omap2_clk_dflt_find_companion, 9762306a36Sopenharmony_ci}; 98