18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * OMAP2/3 interface clock control 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2011 Nokia Corporation 68c2ecf20Sopenharmony_ci * Paul Walmsley 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#undef DEBUG 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 128c2ecf20Sopenharmony_ci#include <linux/io.h> 138c2ecf20Sopenharmony_ci#include <linux/clk/ti.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "clock.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* Register offsets */ 188c2ecf20Sopenharmony_ci#define OMAP24XX_CM_FCLKEN2 0x04 198c2ecf20Sopenharmony_ci#define CM_AUTOIDLE 0x30 208c2ecf20Sopenharmony_ci#define CM_ICLKEN 0x10 218c2ecf20Sopenharmony_ci#define CM_IDLEST 0x20 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define OMAP24XX_CM_IDLEST_VAL 0 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* Private functions */ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* XXX */ 288c2ecf20Sopenharmony_civoid omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci u32 v; 318c2ecf20Sopenharmony_ci struct clk_omap_reg r; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci memcpy(&r, &clk->enable_reg, sizeof(r)); 348c2ecf20Sopenharmony_ci r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci v = ti_clk_ll_ops->clk_readl(&r); 378c2ecf20Sopenharmony_ci v |= (1 << clk->enable_bit); 388c2ecf20Sopenharmony_ci ti_clk_ll_ops->clk_writel(v, &r); 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* XXX */ 428c2ecf20Sopenharmony_civoid omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci u32 v; 458c2ecf20Sopenharmony_ci struct clk_omap_reg r; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci memcpy(&r, &clk->enable_reg, sizeof(r)); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci v = ti_clk_ll_ops->clk_readl(&r); 528c2ecf20Sopenharmony_ci v &= ~(1 << clk->enable_bit); 538c2ecf20Sopenharmony_ci ti_clk_ll_ops->clk_writel(v, &r); 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/** 578c2ecf20Sopenharmony_ci * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS 588c2ecf20Sopenharmony_ci * @clk: struct clk * being enabled 598c2ecf20Sopenharmony_ci * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into 608c2ecf20Sopenharmony_ci * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into 618c2ecf20Sopenharmony_ci * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator 628c2ecf20Sopenharmony_ci * 638c2ecf20Sopenharmony_ci * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the 648c2ecf20Sopenharmony_ci * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE. This custom function 658c2ecf20Sopenharmony_ci * passes back the correct CM_IDLEST register address for I2CHS 668c2ecf20Sopenharmony_ci * modules. No return value. 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_cistatic void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk, 698c2ecf20Sopenharmony_ci struct clk_omap_reg *idlest_reg, 708c2ecf20Sopenharmony_ci u8 *idlest_bit, 718c2ecf20Sopenharmony_ci u8 *idlest_val) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); 748c2ecf20Sopenharmony_ci idlest_reg->offset ^= (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST); 758c2ecf20Sopenharmony_ci *idlest_bit = clk->enable_bit; 768c2ecf20Sopenharmony_ci *idlest_val = OMAP24XX_CM_IDLEST_VAL; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* Public data */ 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_iclk = { 828c2ecf20Sopenharmony_ci .allow_idle = omap2_clkt_iclk_allow_idle, 838c2ecf20Sopenharmony_ci .deny_idle = omap2_clkt_iclk_deny_idle, 848c2ecf20Sopenharmony_ci}; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_iclk_wait = { 878c2ecf20Sopenharmony_ci .allow_idle = omap2_clkt_iclk_allow_idle, 888c2ecf20Sopenharmony_ci .deny_idle = omap2_clkt_iclk_deny_idle, 898c2ecf20Sopenharmony_ci .find_idlest = omap2_clk_dflt_find_idlest, 908c2ecf20Sopenharmony_ci .find_companion = omap2_clk_dflt_find_companion, 918c2ecf20Sopenharmony_ci}; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/* 2430 I2CHS has non-standard IDLEST register */ 948c2ecf20Sopenharmony_ciconst struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = { 958c2ecf20Sopenharmony_ci .find_idlest = omap2430_clk_i2chs_find_idlest, 968c2ecf20Sopenharmony_ci .find_companion = omap2_clk_dflt_find_companion, 978c2ecf20Sopenharmony_ci}; 98