Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * pmic-cpcap.c - CPCAP-specific functions for the OPP code
0004  *
0005  * Adapted from Motorola Mapphone Android Linux kernel
0006  * Copyright (C) 2011 Motorola, Inc.
0007  */
0008 
0009 #include <linux/err.h>
0010 #include <linux/io.h>
0011 #include <linux/kernel.h>
0012 
0013 #include "soc.h"
0014 #include "pm.h"
0015 #include "voltage.h"
0016 
0017 #include <linux/init.h>
0018 #include "vc.h"
0019 
0020 /**
0021  * omap_cpcap_vsel_to_vdc - convert CPCAP VSEL value to microvolts DC
0022  * @vsel: CPCAP VSEL value to convert
0023  *
0024  * Returns the microvolts DC that the CPCAP PMIC should generate when
0025  * programmed with @vsel.
0026  */
0027 static unsigned long omap_cpcap_vsel_to_uv(unsigned char vsel)
0028 {
0029     if (vsel > 0x44)
0030         vsel = 0x44;
0031     return (((vsel * 125) + 6000)) * 100;
0032 }
0033 
0034 /**
0035  * omap_cpcap_uv_to_vsel - convert microvolts DC to CPCAP VSEL value
0036  * @uv: microvolts DC to convert
0037  *
0038  * Returns the VSEL value necessary for the CPCAP PMIC to
0039  * generate an output voltage equal to or greater than @uv microvolts DC.
0040  */
0041 static unsigned char omap_cpcap_uv_to_vsel(unsigned long uv)
0042 {
0043     if (uv < 600000)
0044         uv = 600000;
0045     else if (uv > 1450000)
0046         uv = 1450000;
0047     return DIV_ROUND_UP(uv - 600000, 12500);
0048 }
0049 
0050 static struct omap_voltdm_pmic omap_cpcap_core = {
0051     .slew_rate = 4000,
0052     .step_size = 12500,
0053     .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
0054     .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
0055     .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
0056     .vddmin = 900000,
0057     .vddmax = 1350000,
0058     .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
0059     .i2c_slave_addr = 0x02,
0060     .volt_reg_addr = 0x00,
0061     .cmd_reg_addr = 0x01,
0062     .i2c_high_speed = false,
0063     .vsel_to_uv = omap_cpcap_vsel_to_uv,
0064     .uv_to_vsel = omap_cpcap_uv_to_vsel,
0065 };
0066 
0067 static struct omap_voltdm_pmic omap_cpcap_iva = {
0068     .slew_rate = 4000,
0069     .step_size = 12500,
0070     .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
0071     .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
0072     .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
0073     .vddmin = 900000,
0074     .vddmax = 1375000,
0075     .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
0076     .i2c_slave_addr = 0x44,
0077     .volt_reg_addr = 0x0,
0078     .cmd_reg_addr = 0x01,
0079     .i2c_high_speed = false,
0080     .vsel_to_uv = omap_cpcap_vsel_to_uv,
0081     .uv_to_vsel = omap_cpcap_uv_to_vsel,
0082 };
0083 
0084 /**
0085  * omap_max8952_vsel_to_vdc - convert MAX8952 VSEL value to microvolts DC
0086  * @vsel: MAX8952 VSEL value to convert
0087  *
0088  * Returns the microvolts DC that the MAX8952 Regulator should generate when
0089  * programmed with @vsel.
0090  */
0091 static unsigned long omap_max8952_vsel_to_uv(unsigned char vsel)
0092 {
0093     if (vsel > 0x3F)
0094         vsel = 0x3F;
0095     return (((vsel * 100) + 7700)) * 100;
0096 }
0097 
0098 /**
0099  * omap_max8952_uv_to_vsel - convert microvolts DC to MAX8952 VSEL value
0100  * @uv: microvolts DC to convert
0101  *
0102  * Returns the VSEL value necessary for the MAX8952 Regulator to
0103  * generate an output voltage equal to or greater than @uv microvolts DC.
0104  */
0105 static unsigned char omap_max8952_uv_to_vsel(unsigned long uv)
0106 {
0107     if (uv < 770000)
0108         uv = 770000;
0109     else if (uv > 1400000)
0110         uv = 1400000;
0111     return DIV_ROUND_UP(uv - 770000, 10000);
0112 }
0113 
0114 static struct omap_voltdm_pmic omap443x_max8952_mpu = {
0115     .slew_rate = 16000,
0116     .step_size = 10000,
0117     .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
0118     .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
0119     .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
0120     .vddmin = 900000,
0121     .vddmax = 1400000,
0122     .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
0123     .i2c_slave_addr = 0x60,
0124     .volt_reg_addr = 0x03,
0125     .cmd_reg_addr = 0x03,
0126     .i2c_high_speed = false,
0127     .vsel_to_uv = omap_max8952_vsel_to_uv,
0128     .uv_to_vsel = omap_max8952_uv_to_vsel,
0129 };
0130 
0131 /**
0132  * omap_fan5355_vsel_to_vdc - convert FAN535503 VSEL value to microvolts DC
0133  * @vsel: FAN535503 VSEL value to convert
0134  *
0135  * Returns the microvolts DC that the FAN535503 Regulator should generate when
0136  * programmed with @vsel.
0137  */
0138 static unsigned long omap_fan535503_vsel_to_uv(unsigned char vsel)
0139 {
0140     /* Extract bits[5:0] */
0141     vsel &= 0x3F;
0142 
0143     return (((vsel * 125) + 7500)) * 100;
0144 }
0145 
0146 /**
0147  * omap_fan535508_vsel_to_vdc - convert FAN535508 VSEL value to microvolts DC
0148  * @vsel: FAN535508 VSEL value to convert
0149  *
0150  * Returns the microvolts DC that the FAN535508 Regulator should generate when
0151  * programmed with @vsel.
0152  */
0153 static unsigned long omap_fan535508_vsel_to_uv(unsigned char vsel)
0154 {
0155     /* Extract bits[5:0] */
0156     vsel &= 0x3F;
0157 
0158     if (vsel > 0x37)
0159         vsel = 0x37;
0160     return (((vsel * 125) + 7500)) * 100;
0161 }
0162 
0163 
0164 /**
0165  * omap_fan535503_uv_to_vsel - convert microvolts DC to FAN535503 VSEL value
0166  * @uv: microvolts DC to convert
0167  *
0168  * Returns the VSEL value necessary for the MAX8952 Regulator to
0169  * generate an output voltage equal to or greater than @uv microvolts DC.
0170  */
0171 static unsigned char omap_fan535503_uv_to_vsel(unsigned long uv)
0172 {
0173     unsigned char vsel;
0174     if (uv < 750000)
0175         uv = 750000;
0176     else if (uv > 1537500)
0177         uv = 1537500;
0178 
0179     vsel = DIV_ROUND_UP(uv - 750000, 12500);
0180     return vsel | 0xC0;
0181 }
0182 
0183 /**
0184  * omap_fan535508_uv_to_vsel - convert microvolts DC to FAN535508 VSEL value
0185  * @uv: microvolts DC to convert
0186  *
0187  * Returns the VSEL value necessary for the MAX8952 Regulator to
0188  * generate an output voltage equal to or greater than @uv microvolts DC.
0189  */
0190 static unsigned char omap_fan535508_uv_to_vsel(unsigned long uv)
0191 {
0192     unsigned char vsel;
0193     if (uv < 750000)
0194         uv = 750000;
0195     else if (uv > 1437500)
0196         uv = 1437500;
0197 
0198     vsel = DIV_ROUND_UP(uv - 750000, 12500);
0199     return vsel | 0xC0;
0200 }
0201 
0202 /* fan5335-core */
0203 static struct omap_voltdm_pmic omap4_fan_core = {
0204     .slew_rate = 4000,
0205     .step_size = 12500,
0206     .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
0207     .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
0208     .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
0209     .vddmin = 850000,
0210     .vddmax = 1375000,
0211     .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
0212     .i2c_slave_addr = 0x4A,
0213     .i2c_high_speed = false,
0214     .volt_reg_addr = 0x01,
0215     .cmd_reg_addr = 0x01,
0216     .vsel_to_uv = omap_fan535508_vsel_to_uv,
0217     .uv_to_vsel = omap_fan535508_uv_to_vsel,
0218 };
0219 
0220 /* fan5335 iva */
0221 static struct omap_voltdm_pmic omap4_fan_iva = {
0222     .slew_rate = 4000,
0223     .step_size = 12500,
0224     .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
0225     .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
0226     .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
0227     .vddmin = 850000,
0228     .vddmax = 1375000,
0229     .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
0230     .i2c_slave_addr = 0x48,
0231     .volt_reg_addr = 0x01,
0232     .cmd_reg_addr = 0x01,
0233     .i2c_high_speed = false,
0234     .vsel_to_uv = omap_fan535503_vsel_to_uv,
0235     .uv_to_vsel = omap_fan535503_uv_to_vsel,
0236 };
0237 
0238 int __init omap4_cpcap_init(void)
0239 {
0240     struct voltagedomain *voltdm;
0241 
0242     if (!of_find_compatible_node(NULL, NULL, "motorola,cpcap"))
0243         return -ENODEV;
0244 
0245     voltdm = voltdm_lookup("mpu");
0246     omap_voltage_register_pmic(voltdm, &omap443x_max8952_mpu);
0247 
0248     if (of_machine_is_compatible("motorola,droid-bionic")) {
0249         voltdm = voltdm_lookup("core");
0250         omap_voltage_register_pmic(voltdm, &omap_cpcap_core);
0251 
0252         voltdm = voltdm_lookup("iva");
0253         omap_voltage_register_pmic(voltdm, &omap_cpcap_iva);
0254     } else {
0255         voltdm = voltdm_lookup("core");
0256         omap_voltage_register_pmic(voltdm, &omap4_fan_core);
0257 
0258         voltdm = voltdm_lookup("iva");
0259         omap_voltage_register_pmic(voltdm, &omap4_fan_iva);
0260     }
0261 
0262     return 0;
0263 }
0264 
0265 static int __init cpcap_late_init(void)
0266 {
0267     omap4_vc_set_pmic_signaling(PWRDM_POWER_RET);
0268 
0269     return 0;
0270 }
0271 omap_late_initcall(cpcap_late_init);