Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");