123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * pmic-cpcap.c - CPCAP-specific functions for the OPP code
- *
- * Adapted from Motorola Mapphone Android Linux kernel
- * Copyright (C) 2011 Motorola, Inc.
- */
- #include <linux/err.h>
- #include <linux/io.h>
- #include <linux/kernel.h>
- #include "soc.h"
- #include "pm.h"
- #include "voltage.h"
- #include <linux/init.h>
- #include "vc.h"
- /**
- * omap_cpcap_vsel_to_vdc - convert CPCAP VSEL value to microvolts DC
- * @vsel: CPCAP VSEL value to convert
- *
- * Returns the microvolts DC that the CPCAP PMIC should generate when
- * programmed with @vsel.
- */
- static unsigned long omap_cpcap_vsel_to_uv(unsigned char vsel)
- {
- if (vsel > 0x44)
- vsel = 0x44;
- return (((vsel * 125) + 6000)) * 100;
- }
- /**
- * omap_cpcap_uv_to_vsel - convert microvolts DC to CPCAP VSEL value
- * @uv: microvolts DC to convert
- *
- * Returns the VSEL value necessary for the CPCAP PMIC to
- * generate an output voltage equal to or greater than @uv microvolts DC.
- */
- static unsigned char omap_cpcap_uv_to_vsel(unsigned long uv)
- {
- if (uv < 600000)
- uv = 600000;
- else if (uv > 1450000)
- uv = 1450000;
- return DIV_ROUND_UP(uv - 600000, 12500);
- }
- static struct omap_voltdm_pmic omap_cpcap_core = {
- .slew_rate = 4000,
- .step_size = 12500,
- .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
- .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
- .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
- .vddmin = 900000,
- .vddmax = 1350000,
- .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
- .i2c_slave_addr = 0x02,
- .volt_reg_addr = 0x00,
- .cmd_reg_addr = 0x01,
- .i2c_high_speed = false,
- .vsel_to_uv = omap_cpcap_vsel_to_uv,
- .uv_to_vsel = omap_cpcap_uv_to_vsel,
- };
- static struct omap_voltdm_pmic omap_cpcap_iva = {
- .slew_rate = 4000,
- .step_size = 12500,
- .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
- .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
- .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
- .vddmin = 900000,
- .vddmax = 1375000,
- .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
- .i2c_slave_addr = 0x44,
- .volt_reg_addr = 0x0,
- .cmd_reg_addr = 0x01,
- .i2c_high_speed = false,
- .vsel_to_uv = omap_cpcap_vsel_to_uv,
- .uv_to_vsel = omap_cpcap_uv_to_vsel,
- };
- /**
- * omap_max8952_vsel_to_vdc - convert MAX8952 VSEL value to microvolts DC
- * @vsel: MAX8952 VSEL value to convert
- *
- * Returns the microvolts DC that the MAX8952 Regulator should generate when
- * programmed with @vsel.
- */
- static unsigned long omap_max8952_vsel_to_uv(unsigned char vsel)
- {
- if (vsel > 0x3F)
- vsel = 0x3F;
- return (((vsel * 100) + 7700)) * 100;
- }
- /**
- * omap_max8952_uv_to_vsel - convert microvolts DC to MAX8952 VSEL value
- * @uv: microvolts DC to convert
- *
- * Returns the VSEL value necessary for the MAX8952 Regulator to
- * generate an output voltage equal to or greater than @uv microvolts DC.
- */
- static unsigned char omap_max8952_uv_to_vsel(unsigned long uv)
- {
- if (uv < 770000)
- uv = 770000;
- else if (uv > 1400000)
- uv = 1400000;
- return DIV_ROUND_UP(uv - 770000, 10000);
- }
- static struct omap_voltdm_pmic omap443x_max8952_mpu = {
- .slew_rate = 16000,
- .step_size = 10000,
- .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
- .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
- .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
- .vddmin = 900000,
- .vddmax = 1400000,
- .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
- .i2c_slave_addr = 0x60,
- .volt_reg_addr = 0x03,
- .cmd_reg_addr = 0x03,
- .i2c_high_speed = false,
- .vsel_to_uv = omap_max8952_vsel_to_uv,
- .uv_to_vsel = omap_max8952_uv_to_vsel,
- };
- /**
- * omap_fan5355_vsel_to_vdc - convert FAN535503 VSEL value to microvolts DC
- * @vsel: FAN535503 VSEL value to convert
- *
- * Returns the microvolts DC that the FAN535503 Regulator should generate when
- * programmed with @vsel.
- */
- static unsigned long omap_fan535503_vsel_to_uv(unsigned char vsel)
- {
- /* Extract bits[5:0] */
- vsel &= 0x3F;
- return (((vsel * 125) + 7500)) * 100;
- }
- /**
- * omap_fan535508_vsel_to_vdc - convert FAN535508 VSEL value to microvolts DC
- * @vsel: FAN535508 VSEL value to convert
- *
- * Returns the microvolts DC that the FAN535508 Regulator should generate when
- * programmed with @vsel.
- */
- static unsigned long omap_fan535508_vsel_to_uv(unsigned char vsel)
- {
- /* Extract bits[5:0] */
- vsel &= 0x3F;
- if (vsel > 0x37)
- vsel = 0x37;
- return (((vsel * 125) + 7500)) * 100;
- }
- /**
- * omap_fan535503_uv_to_vsel - convert microvolts DC to FAN535503 VSEL value
- * @uv: microvolts DC to convert
- *
- * Returns the VSEL value necessary for the MAX8952 Regulator to
- * generate an output voltage equal to or greater than @uv microvolts DC.
- */
- static unsigned char omap_fan535503_uv_to_vsel(unsigned long uv)
- {
- unsigned char vsel;
- if (uv < 750000)
- uv = 750000;
- else if (uv > 1537500)
- uv = 1537500;
- vsel = DIV_ROUND_UP(uv - 750000, 12500);
- return vsel | 0xC0;
- }
- /**
- * omap_fan535508_uv_to_vsel - convert microvolts DC to FAN535508 VSEL value
- * @uv: microvolts DC to convert
- *
- * Returns the VSEL value necessary for the MAX8952 Regulator to
- * generate an output voltage equal to or greater than @uv microvolts DC.
- */
- static unsigned char omap_fan535508_uv_to_vsel(unsigned long uv)
- {
- unsigned char vsel;
- if (uv < 750000)
- uv = 750000;
- else if (uv > 1437500)
- uv = 1437500;
- vsel = DIV_ROUND_UP(uv - 750000, 12500);
- return vsel | 0xC0;
- }
- /* fan5335-core */
- static struct omap_voltdm_pmic omap4_fan_core = {
- .slew_rate = 4000,
- .step_size = 12500,
- .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
- .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
- .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
- .vddmin = 850000,
- .vddmax = 1375000,
- .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
- .i2c_slave_addr = 0x4A,
- .i2c_high_speed = false,
- .volt_reg_addr = 0x01,
- .cmd_reg_addr = 0x01,
- .vsel_to_uv = omap_fan535508_vsel_to_uv,
- .uv_to_vsel = omap_fan535508_uv_to_vsel,
- };
- /* fan5335 iva */
- static struct omap_voltdm_pmic omap4_fan_iva = {
- .slew_rate = 4000,
- .step_size = 12500,
- .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
- .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
- .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
- .vddmin = 850000,
- .vddmax = 1375000,
- .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
- .i2c_slave_addr = 0x48,
- .volt_reg_addr = 0x01,
- .cmd_reg_addr = 0x01,
- .i2c_high_speed = false,
- .vsel_to_uv = omap_fan535503_vsel_to_uv,
- .uv_to_vsel = omap_fan535503_uv_to_vsel,
- };
- int __init omap4_cpcap_init(void)
- {
- struct voltagedomain *voltdm;
- if (!of_find_compatible_node(NULL, NULL, "motorola,cpcap"))
- return -ENODEV;
- voltdm = voltdm_lookup("mpu");
- omap_voltage_register_pmic(voltdm, &omap443x_max8952_mpu);
- if (of_machine_is_compatible("motorola,droid-bionic")) {
- voltdm = voltdm_lookup("core");
- omap_voltage_register_pmic(voltdm, &omap_cpcap_core);
- voltdm = voltdm_lookup("iva");
- omap_voltage_register_pmic(voltdm, &omap_cpcap_iva);
- } else {
- voltdm = voltdm_lookup("core");
- omap_voltage_register_pmic(voltdm, &omap4_fan_core);
- voltdm = voltdm_lookup("iva");
- omap_voltage_register_pmic(voltdm, &omap4_fan_iva);
- }
- return 0;
- }
- static int __init cpcap_late_init(void)
- {
- omap4_vc_set_pmic_signaling(PWRDM_POWER_RET);
- return 0;
- }
- omap_late_initcall(cpcap_late_init);
|