^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * OMAP SmartReflex Voltage Control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Thara Gopinath <thara@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2012 Texas Instruments, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Thara Gopinath <thara@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2008 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Kalle Jokiniemi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright (C) 2007 Texas Instruments, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Lesly A M <x0080970@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/power/smartreflex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define DRIVER_NAME "smartreflex"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SMARTREFLEX_NAME_LEN 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define NVALUE_NAME_LEN 40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SR_DISABLE_TIMEOUT 200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* sr_list contains all the instances of smartreflex module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static LIST_HEAD(sr_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static struct omap_sr_class_data *sr_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static struct dentry *sr_dbg_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) __raw_writel(value, (sr->base + offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u32 reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * Smartreflex error config register is special as it contains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * certain status bits which if written a 1 into means a clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * of those bits. So in order to make sure no accidental write of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * 1 happens to those status bits, do a clear of them in the read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * value. This mean this API doesn't rewrite values in these bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * if they are currently set, but does allow the caller to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * those bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (sr->ip_type == SR_TYPE_V1 && offset == ERRCONFIG_V1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) mask |= ERRCONFIG_STATUS_V1_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) else if (sr->ip_type == SR_TYPE_V2 && offset == ERRCONFIG_V2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) mask |= ERRCONFIG_VPBOUNDINTST_V2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) reg_val = __raw_readl(sr->base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) reg_val &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) value &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) reg_val |= value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) __raw_writel(reg_val, (sr->base + offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return __raw_readl(sr->base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct omap_sr *sr_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!voltdm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) pr_err("%s: Null voltage domain passed!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) list_for_each_entry(sr_info, &sr_list, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (voltdm == sr_info->voltdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return sr_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return ERR_PTR(-ENODATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static irqreturn_t sr_interrupt(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct omap_sr *sr_info = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u32 status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) switch (sr_info->ip_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) case SR_TYPE_V1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* Read the status bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) status = sr_read_reg(sr_info, ERRCONFIG_V1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* Clear them by writing back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) sr_write_reg(sr_info, ERRCONFIG_V1, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) case SR_TYPE_V2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* Read the status bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) status = sr_read_reg(sr_info, IRQSTATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Clear them by writing back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) sr_write_reg(sr_info, IRQSTATUS, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) dev_err(&sr_info->pdev->dev, "UNKNOWN IP type %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) sr_info->ip_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (sr_class->notify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) sr_class->notify(sr_info, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static void sr_set_clk_length(struct omap_sr *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct clk *fck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u32 fclk_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* Try interconnect target module fck first if it already exists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) fck = clk_get(sr->pdev->dev.parent, "fck");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (IS_ERR(fck)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) fck = clk_get(&sr->pdev->dev, "fck");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (IS_ERR(fck)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) dev_err(&sr->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) "%s: unable to get fck for device %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) __func__, dev_name(&sr->pdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) fclk_speed = clk_get_rate(fck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) clk_put(fck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) switch (fclk_speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) case 12000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) case 13000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) case 19200000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) case 26000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case 38400000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dev_err(&sr->pdev->dev, "%s: Invalid fclk rate: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) __func__, fclk_speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static void sr_start_vddautocomp(struct omap_sr *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) dev_warn(&sr->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) "%s: smartreflex class driver not registered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (!sr_class->enable(sr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) sr->autocomp_active = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void sr_stop_vddautocomp(struct omap_sr *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!sr_class || !(sr_class->disable)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) dev_warn(&sr->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) "%s: smartreflex class driver not registered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (sr->autocomp_active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) sr_class->disable(sr, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) sr->autocomp_active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * This function handles the initializations which have to be done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * only when both sr device and class driver regiter has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * completed. This will be attempted to be called from both sr class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * driver register and sr device intializtion API's. Only one call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * will ultimately succeed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * Currently this function registers interrupt handler for a particular SR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * if smartreflex class driver is already registered and has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * requested for interrupts and the SR interrupt line in present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int sr_late_init(struct omap_sr *sr_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ret = devm_request_irq(&sr_info->pdev->dev, sr_info->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) sr_interrupt, 0, sr_info->name, sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) disable_irq(sr_info->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (pdata && pdata->enable_on_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) sr_start_vddautocomp(sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) list_del(&sr_info->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) dev_err(&sr_info->pdev->dev, "%s: ERROR in registering interrupt handler. Smartreflex will not function as desired\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static void sr_v1_disable(struct omap_sr *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int timeout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int errconf_val = ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ERRCONFIG_MCUBOUNDINTST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* Enable MCUDisableAcknowledge interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) sr_modify_reg(sr, ERRCONFIG_V1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* SRCONFIG - disable SR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* Disable all other SR interrupts and clear the status as needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (sr_read_reg(sr, ERRCONFIG_V1) & ERRCONFIG_VPBOUNDINTST_V1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) errconf_val |= ERRCONFIG_VPBOUNDINTST_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) sr_modify_reg(sr, ERRCONFIG_V1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) errconf_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Wait for SR to be disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) sr_test_cond_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (timeout >= SR_DISABLE_TIMEOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ERRCONFIG_MCUDISACKINTST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static void sr_v2_disable(struct omap_sr *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int timeout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* Enable MCUDisableAcknowledge interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* SRCONFIG - disable SR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * Disable all other SR interrupts and clear the status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * write to status register ONLY on need basis - only if status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (sr_read_reg(sr, ERRCONFIG_V2) & ERRCONFIG_VPBOUNDINTST_V2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ERRCONFIG_VPBOUNDINTST_V2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) IRQENABLE_MCUVALIDINT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) IRQENABLE_MCUBOUNDSINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) IRQSTATUS_MCVALIDINT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) IRQSTATUS_MCBOUNDSINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * Wait for SR to be disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) sr_test_cond_timeout((sr_read_reg(sr, IRQSTATUS) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (timeout >= SR_DISABLE_TIMEOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct omap_sr *sr, u32 efuse_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (!sr->nvalue_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) for (i = 0; i < sr->nvalue_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (sr->nvalue_table[i].efuse_offs == efuse_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return &sr->nvalue_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* Public Functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * sr_configure_errgen() - Configures the SmartReflex to perform AVS using the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * error generator module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * @sr: SR module to be configured.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * This API is to be called from the smartreflex class driver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * configure the error generator module inside the smartreflex module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * SR settings if using the ERROR module inside Smartreflex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * SR CLASS 3 by default uses only the ERROR module where as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * SR CLASS 2 can choose between ERROR module and MINMAXAVG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * module. Returns 0 on success and error value in case of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) int sr_configure_errgen(struct omap_sr *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) u32 sr_config, sr_errconfig, errconfig_offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) u32 vpboundint_en, vpboundint_st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) u32 senp_en = 0, senn_en = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) u8 senp_shift, senn_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!sr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) pr_warn("%s: NULL omap_sr from %pS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) __func__, (void *)_RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (!sr->clk_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) sr_set_clk_length(sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) senp_en = sr->senp_mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) senn_en = sr->senn_mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) switch (sr->ip_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) case SR_TYPE_V1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) sr_config |= SRCONFIG_DELAYCTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) errconfig_offs = ERRCONFIG_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) case SR_TYPE_V2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) errconfig_offs = ERRCONFIG_V2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex module without specifying the ip\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) sr_write_reg(sr, SRCONFIG, sr_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) (sr->err_minlimit << ERRCONFIG_ERRMINLIMIT_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) sr_errconfig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* Enabling the interrupts if the ERROR module is used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) sr_modify_reg(sr, errconfig_offs, (vpboundint_en | vpboundint_st),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) vpboundint_en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * sr_disable_errgen() - Disables SmartReflex AVS module's errgen component
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * @sr: SR module to be configured.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * This API is to be called from the smartreflex class driver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * disable the error generator module inside the smartreflex module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * Returns 0 on success and error value in case of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) int sr_disable_errgen(struct omap_sr *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) u32 errconfig_offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) u32 vpboundint_en, vpboundint_st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (!sr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) pr_warn("%s: NULL omap_sr from %pS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) __func__, (void *)_RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) switch (sr->ip_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) case SR_TYPE_V1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) errconfig_offs = ERRCONFIG_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) case SR_TYPE_V2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) errconfig_offs = ERRCONFIG_V2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex module without specifying the ip\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* Disable the Sensor and errorgen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) sr_modify_reg(sr, SRCONFIG, SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * Disable the interrupts of ERROR module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * NOTE: modify is a read, modify,write - an implicit OCP barrier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * which is required is present here - sequencing is critical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * at this point (after errgen is disabled, vpboundint disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) sr_modify_reg(sr, errconfig_offs, vpboundint_en | vpboundint_st, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * sr_configure_minmax() - Configures the SmartReflex to perform AVS using the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * minmaxavg module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * @sr: SR module to be configured.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * This API is to be called from the smartreflex class driver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * configure the minmaxavg module inside the smartreflex module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * SR settings if using the ERROR module inside Smartreflex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * SR CLASS 3 by default uses only the ERROR module where as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * SR CLASS 2 can choose between ERROR module and MINMAXAVG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * module. Returns 0 on success and error value in case of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) int sr_configure_minmax(struct omap_sr *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) u32 sr_config, sr_avgwt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) u32 senp_en = 0, senn_en = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) u8 senp_shift, senn_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (!sr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) pr_warn("%s: NULL omap_sr from %pS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) __func__, (void *)_RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (!sr->clk_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) sr_set_clk_length(sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) senp_en = sr->senp_mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) senn_en = sr->senn_mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) SRCONFIG_SENENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) (sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) switch (sr->ip_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) case SR_TYPE_V1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) sr_config |= SRCONFIG_DELAYCTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) case SR_TYPE_V2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex module without specifying the ip\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) sr_write_reg(sr, SRCONFIG, sr_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) sr_write_reg(sr, AVGWEIGHT, sr_avgwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * Enabling the interrupts if MINMAXAVG module is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * TODO: check if all the interrupts are mandatory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) switch (sr->ip_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) case SR_TYPE_V1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) sr_modify_reg(sr, ERRCONFIG_V1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ERRCONFIG_MCUBOUNDINTEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) case SR_TYPE_V2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) sr_write_reg(sr, IRQSTATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) sr_write_reg(sr, IRQENABLE_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex module without specifying the ip\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * sr_enable() - Enables the smartreflex module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * @sr: pointer to which the SR module to be configured belongs to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * @volt: The voltage at which the Voltage domain associated with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * the smartreflex module is operating at.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * This is required only to program the correct Ntarget value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * This API is to be called from the smartreflex class driver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * enable a smartreflex module. Returns 0 on success. Returns error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * value if the voltage passed is wrong or if ntarget value is wrong.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) int sr_enable(struct omap_sr *sr, unsigned long volt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct omap_volt_data *volt_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct omap_sr_nvalue_table *nvalue_row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (!sr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) pr_warn("%s: NULL omap_sr from %pS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) __func__, (void *)_RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) volt_data = omap_voltage_get_voltdata(sr->voltdm, volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (IS_ERR(volt_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table for nominal voltage %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) __func__, volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return PTR_ERR(volt_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) nvalue_row = sr_retrieve_nvalue_row(sr, volt_data->sr_efuse_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (!nvalue_row) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) dev_warn(&sr->pdev->dev, "%s: failure getting SR data for this voltage %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) __func__, volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* errminlimit is opp dependent and hence linked to voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) sr->err_minlimit = nvalue_row->errminlimit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) pm_runtime_get_sync(&sr->pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) /* Check if SR is already enabled. If yes do nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /* Configure SR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) ret = sr_class->configure(sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) /* SRCONFIG - enable SR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * sr_disable() - Disables the smartreflex module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * @sr: pointer to which the SR module to be configured belongs to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * This API is to be called from the smartreflex class driver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * disable a smartreflex module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) void sr_disable(struct omap_sr *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (!sr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) pr_warn("%s: NULL omap_sr from %pS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) __func__, (void *)_RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /* Check if SR clocks are already disabled. If yes do nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (pm_runtime_suspended(&sr->pdev->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * Disable SR if only it is indeed enabled. Else just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * disable the clocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) switch (sr->ip_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) case SR_TYPE_V1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) sr_v1_disable(sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) case SR_TYPE_V2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) sr_v2_disable(sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) dev_err(&sr->pdev->dev, "UNKNOWN IP type %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) sr->ip_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) pm_runtime_put_sync_suspend(&sr->pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * sr_register_class() - API to register a smartreflex class parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * @class_data: The structure containing various sr class specific data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * This API is to be called by the smartreflex class driver to register itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * with the smartreflex driver during init. Returns 0 on success else the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * error value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) int sr_register_class(struct omap_sr_class_data *class_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct omap_sr *sr_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (!class_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) pr_warn("%s:, Smartreflex class data passed is NULL\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (sr_class) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) pr_warn("%s: Smartreflex class driver already registered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) sr_class = class_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * Call into late init to do initializations that require
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * both sr driver and sr class driver to be initiallized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) list_for_each_entry(sr_info, &sr_list, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) sr_late_init(sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * omap_sr_enable() - API to enable SR clocks and to call into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * registered smartreflex class enable API.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * @voltdm: VDD pointer to which the SR module to be configured belongs to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * This API is to be called from the kernel in order to enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * a particular smartreflex module. This API will do the initial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * configurations to turn on the smartreflex module and in turn call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * into the registered smartreflex class enable API.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) void omap_sr_enable(struct voltagedomain *voltdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct omap_sr *sr = _sr_lookup(voltdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (IS_ERR(sr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) pr_warn("%s: omap_sr struct for voltdm not found\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (!sr->autocomp_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) sr_class->enable(sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * omap_sr_disable() - API to disable SR without resetting the voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * processor voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * @voltdm: VDD pointer to which the SR module to be configured belongs to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * This API is to be called from the kernel in order to disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * a particular smartreflex module. This API will in turn call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * into the registered smartreflex class disable API. This API will tell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * the smartreflex class disable not to reset the VP voltage after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * disabling smartreflex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) void omap_sr_disable(struct voltagedomain *voltdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct omap_sr *sr = _sr_lookup(voltdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (IS_ERR(sr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) pr_warn("%s: omap_sr struct for voltdm not found\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (!sr->autocomp_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (!sr_class || !(sr_class->disable)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) sr_class->disable(sr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * omap_sr_disable_reset_volt() - API to disable SR and reset the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * voltage processor voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * @voltdm: VDD pointer to which the SR module to be configured belongs to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * This API is to be called from the kernel in order to disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * a particular smartreflex module. This API will in turn call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * into the registered smartreflex class disable API. This API will tell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * the smartreflex class disable to reset the VP voltage after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * disabling smartreflex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) struct omap_sr *sr = _sr_lookup(voltdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (IS_ERR(sr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) pr_warn("%s: omap_sr struct for voltdm not found\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (!sr->autocomp_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (!sr_class || !(sr_class->disable)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) sr_class->disable(sr, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* PM Debug FS entries to enable and disable smartreflex. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) static int omap_sr_autocomp_show(void *data, u64 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct omap_sr *sr_info = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (!sr_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) pr_warn("%s: omap_sr struct not found\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) *val = sr_info->autocomp_active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static int omap_sr_autocomp_store(void *data, u64 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct omap_sr *sr_info = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (!sr_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) pr_warn("%s: omap_sr struct not found\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* Sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (val > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) pr_warn("%s: Invalid argument %lld\n", __func__, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) /* control enable/disable only if there is a delta in value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (sr_info->autocomp_active != val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) sr_stop_vddautocomp(sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) sr_start_vddautocomp(sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) omap_sr_autocomp_store, "%llu\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static int omap_sr_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct omap_sr *sr_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) struct omap_sr_data *pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) struct resource *mem, *irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct dentry *nvalue_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) sr_info = devm_kzalloc(&pdev->dev, sizeof(struct omap_sr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (!sr_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) sr_info->name = devm_kzalloc(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) SMARTREFLEX_NAME_LEN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (!sr_info->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) platform_set_drvdata(pdev, sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) sr_info->base = devm_ioremap_resource(&pdev->dev, mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (IS_ERR(sr_info->base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return PTR_ERR(sr_info->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) pm_runtime_enable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) pm_runtime_irq_safe(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) snprintf(sr_info->name, SMARTREFLEX_NAME_LEN, "%s", pdata->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) sr_info->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) sr_info->srid = pdev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) sr_info->voltdm = pdata->voltdm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) sr_info->nvalue_table = pdata->nvalue_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) sr_info->nvalue_count = pdata->nvalue_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) sr_info->senn_mod = pdata->senn_mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) sr_info->senp_mod = pdata->senp_mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) sr_info->err_weight = pdata->err_weight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) sr_info->err_maxlimit = pdata->err_maxlimit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) sr_info->accum_data = pdata->accum_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) sr_info->senn_avgweight = pdata->senn_avgweight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) sr_info->senp_avgweight = pdata->senp_avgweight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) sr_info->autocomp_active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) sr_info->ip_type = pdata->ip_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) sr_info->irq = irq->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) sr_set_clk_length(sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) list_add(&sr_info->node, &sr_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) ret = pm_runtime_get_sync(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) pm_runtime_put_noidle(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) goto err_list_del;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) * Call into late init to do initializations that require
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) * both sr driver and sr class driver to be initiallized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (sr_class) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) ret = sr_late_init(sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) pr_warn("%s: Error in SR late init\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) goto err_list_del;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (!sr_dbg_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) sr_info->dbg_dir = debugfs_create_dir(sr_info->name, sr_dbg_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, sr_info->dbg_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) sr_info, &pm_sr_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) debugfs_create_x32("errweight", S_IRUGO, sr_info->dbg_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) &sr_info->err_weight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) &sr_info->err_maxlimit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (sr_info->nvalue_count == 0 || !sr_info->nvalue_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) dev_warn(&pdev->dev, "%s: %s: No Voltage table for the corresponding vdd. Cannot create debugfs entries for n-values\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) __func__, sr_info->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) ret = -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) goto err_debugfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) for (i = 0; i < sr_info->nvalue_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) char name[NVALUE_NAME_LEN + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) snprintf(name, sizeof(name), "volt_%lu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) sr_info->nvalue_table[i].volt_nominal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) &(sr_info->nvalue_table[i].nvalue));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) snprintf(name, sizeof(name), "errminlimit_%lu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) sr_info->nvalue_table[i].volt_nominal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) &(sr_info->nvalue_table[i].errminlimit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) pm_runtime_put_sync(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) err_debugfs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) debugfs_remove_recursive(sr_info->dbg_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) err_list_del:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) list_del(&sr_info->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) pm_runtime_put_sync(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) static int omap_sr_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct omap_sr_data *pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) struct omap_sr *sr_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) sr_info = _sr_lookup(pdata->voltdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (IS_ERR(sr_info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return PTR_ERR(sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (sr_info->autocomp_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) sr_stop_vddautocomp(sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) debugfs_remove_recursive(sr_info->dbg_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) pm_runtime_disable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) list_del(&sr_info->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) static void omap_sr_shutdown(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) struct omap_sr_data *pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) struct omap_sr *sr_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) sr_info = _sr_lookup(pdata->voltdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (IS_ERR(sr_info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (sr_info->autocomp_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) sr_stop_vddautocomp(sr_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) static const struct of_device_id omap_sr_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) { .compatible = "ti,omap3-smartreflex-core", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) { .compatible = "ti,omap3-smartreflex-mpu-iva", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) { .compatible = "ti,omap4-smartreflex-core", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) { .compatible = "ti,omap4-smartreflex-mpu", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) { .compatible = "ti,omap4-smartreflex-iva", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) MODULE_DEVICE_TABLE(of, omap_sr_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) static struct platform_driver smartreflex_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) .probe = omap_sr_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) .remove = omap_sr_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) .shutdown = omap_sr_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) .of_match_table = omap_sr_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) static int __init sr_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) ret = platform_driver_register(&smartreflex_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) pr_err("%s: platform driver register failed for SR\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) late_initcall(sr_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) static void __exit sr_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) platform_driver_unregister(&smartreflex_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) module_exit(sr_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) MODULE_DESCRIPTION("OMAP Smartreflex Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) MODULE_ALIAS("platform:" DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) MODULE_AUTHOR("Texas Instruments Inc");