From: Robin Gong Date: Mon, 19 Dec 2011 10:09:25 +0000 (+0800) Subject: ENGR00170255-3 MX6Q PFUZE100: add regulator driver of pfuze100 X-Git-Tag: v3.0.35-fsl_4.1.0~1885 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=407e67a20c33ee6be2232b0bcf007638947fcfff;p=karo-tx-linux.git ENGR00170255-3 MX6Q PFUZE100: add regulator driver of pfuze100 add new regulator driver for pfuze100 based on mfd structure Signed-off-by: Robin Gong --- diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index f996525305ed..8ba178f0d8ee 100755 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -220,7 +220,12 @@ config REGULATOR_MC34708 help Say y here to support the regulators found on the Freescale MC34708 PMIC. - +config REGULATOR_PFUZE100 + tristate "Support regulators on Freescale PFUZE100 PMIC" + depends on MFD_PFUZE + help + Say y here to support the regulators found on the Freescale PFUZE100 + PMIC. config REGULATOR_AB3100 tristate "ST-Ericsson AB3100 Regulator functions" depends on AB3100_CORE diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index ed0c60604da0..dc7496cbe78a 100755 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o obj-$(CONFIG_REGULATOR_MC34708) += mc34708-regulator.o +obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o diff --git a/drivers/regulator/pfuze-regulator.h b/drivers/regulator/pfuze-regulator.h new file mode 100644 index 000000000000..0ce1c8b62e89 --- /dev/null +++ b/drivers/regulator/pfuze-regulator.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __LINUX_REGULATOR_PFUZE_H +#define __LINUX_REGULATOR_PFUZE_H + +#include + +struct pfuze_regulator { + struct regulator_desc desc; + unsigned int reg; + unsigned char enable_bit; + unsigned char vsel_shift; + unsigned char vsel_mask; + int const *voltages; +}; + +struct pfuze_regulator_priv { + struct mc_pfuze *pfuze; + struct pfuze_regulator *pfuze_regulators; + struct regulator_dev *regulators[]; +}; + +#define PFUZE_DEFINE(prefix, _name, _reg, _voltages, _ops) \ + [prefix ## _name] = { \ + .desc = { \ + .name = #prefix "_" #_name, \ + .n_voltages = ARRAY_SIZE(_voltages), \ + .ops = &_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = prefix ## _name, \ + .owner = THIS_MODULE, \ + }, \ + .reg = prefix ## _reg, \ + .enable_bit = prefix ## _reg ## _ ## EN, \ + .vsel_shift = prefix ## _reg ## _ ## VSEL,\ + .vsel_mask = prefix ## _reg ## _ ## VSEL_M,\ + .voltages = _voltages, \ + } +#define PFUZE_SW_DEFINE(prefix, _name, _reg, _voltages, _ops) \ + [prefix ## _name] = { \ + .desc = { \ + .name = #prefix "_" #_name, \ + .n_voltages = ARRAY_SIZE(_voltages), \ + .ops = &_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = prefix ## _name, \ + .owner = THIS_MODULE, \ + }, \ + .reg = prefix ## _reg, \ + .vsel_shift = prefix ## _reg ## _ ## VSEL,\ + .vsel_mask = prefix ## _reg ## _ ## VSEL_M,\ + .voltages = _voltages, \ + } + +#define PFUZE_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops) \ + [prefix ## _name] = { \ + .desc = { \ + .name = #prefix "_" #_name, \ + .n_voltages = ARRAY_SIZE(_voltages), \ + .ops = &_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = prefix ## _name, \ + .owner = THIS_MODULE, \ + }, \ + .reg = prefix ## _reg, \ + .enable_bit = prefix ## _reg ## _ ## EN, \ + .voltages = _voltages, \ + } + +#endif + diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c new file mode 100644 index 000000000000..afa24ab454f6 --- /dev/null +++ b/drivers/regulator/pfuze100-regulator.c @@ -0,0 +1,771 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "pfuze-regulator.h" + +static const int pfuze100_sw1[] = { +#ifdef PFUZE100_FIRST_VERSION + 650000, 662500, 675000, 687500, 700000, 712500, 725000, 737500, + 750000, 762500, 775000, 787500, 800000, 812500, 825000, 837500, + 850000, 862500, 875000, 887500, 900000, 912500, 925000, 937500, + 950000, 962500, 975000, 987500, 1000000, 1012500, 1025000, 1037500, + 1050000, 1062500, 1075000, 1087500, 1100000, 1112500, 1125000, 1137500, + 1150000, 1162500, 1175000, 1187500, 1200000, 1212500, 1225000, 1237500, + 1250000, 1262500, 1275000, 1287500, 1300000, 1312500, 1325000, 1337500, + 1350000, 1362500, 1375000, 1387500, 1400000, 1412500, 1425000, 1437500, +#else + 300000, 325000, 350000, 375000, 400000, 425000, 450000, 475000, + 500000, 525000, 550000, 575000, 600000, 625000, 650000, 675000, + 700000, 725000, 750000, 775000, 800000, 825000, 850000, 875000, + 900000, 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, + 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, + 1300000, 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, + 1500000, 1525000, 1550000, 1575000, 1600000, 1625000, 1650000, 1675000, + 1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000, +#endif +}; + +#if PFUZE100_SW2_VOL6 +static const int pfuze100_sw2[] = { + 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, + 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, + 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, + 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000, + 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000, + 2800000, 2850000, 2900000, 2950000, 3000000, 3050000, 3100000, 3150000, + 3200000, 3250000, 3300000, 3300000, 3300000, 3300000, 3300000, 3300000, + 3300000, 3300000, 3300000, 3300000, 3300000, 3300000, 3300000, 3950000, +}; +#else +static const int pfuze100_sw2[] = { + 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, + 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, + 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, + 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, + 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, + 1400000, 1425000, 1450000, 1475000, 1500000, 1525000, 1550000, 1575000, + 1600000, 1625000, 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, + 1800000, 1825000, 1850000, 1875000, 1900000, 1925000, 1950000, 1975000, +}; +#endif + +#if PFUZE100_SW3_VOL6 +static const int pfuze100_sw3[] = { + 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, + 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, + 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, + 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000, + 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000, + 2800000, 2850000, 2900000, 2950000, 3000000, 3050000, 3100000, 3150000, + 3200000, 3250000, 3300000, 3300000, 3300000, 3300000, 3300000, 3300000, + 3300000, 3300000, 3300000, 3750000, 3800000, 3850000, 3900000, 3950000, +}; +#else +static const int pfuze100_sw3[] = { + 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, + 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, + 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, + 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, + 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, + 1400000, 1425000, 1450000, 1475000, 1500000, 1525000, 1550000, 1575000, + 1600000, 1625000, 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, + 1800000, 1825000, 1850000, 1875000, 1900000, 1925000, 1950000, 1975000, +}; +#endif + +#if PFUZE100_SW4_VOL6 +static const int pfuze100_sw4[] = { + 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, + 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, + 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, + 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000, + 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000, + 2800000, 2850000, 2900000, 2950000, 3000000, 3050000, 3100000, 3150000, + 3200000, 3250000, 3300000, 3300000, 3300000, 3300000, 3300000, 3300000, + 3300000, 3300000, 3300000, 3300000, 3300000, 3300000, 3300000, 3950000, +}; + +#else +static const int pfuze100_sw4[] = { + 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, + 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, + 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, + 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, + 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, + 1400000, 1425000, 1450000, 1475000, 1500000, 1525000, 1550000, 1575000, + 1600000, 1625000, 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, + 1800000, 1825000, 1850000, 1875000, 1900000, 1925000, 1950000, 1975000, +}; +#endif + +static const int pfuze100_swbst[] = { + 5000000, 5050000, 5100000, 5150000, +}; + +static const int pfuze100_vsnvs[] = { + 1200000, 1500000, 1800000, 3000000, +}; + +static const int pfuze100_vrefddr[] = { + 750000, +}; + +static const int pfuze100_vgen12[] = { + +#ifdef PFUZE100_FIRST_VERSION + 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, +#else + 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, + 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, +#endif +}; + +static const int pfuze100_vgen36[] = { + 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, + 2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000, +}; + +static struct regulator_ops pfuze100_ldo_regulator_ops; +static struct regulator_ops pfuze100_fixed_regulator_ops; +static struct regulator_ops pfuze100_sw_regulator_ops; + +#define PFUZE100_FIXED_VOL_DEFINE(name, reg, voltages) \ + PFUZE_FIXED_DEFINE(PFUZE100_, name, reg, voltages, \ + pfuze100_fixed_regulator_ops) + +#define PFUZE100_SW_DEFINE(name, reg, voltages) \ + PFUZE_SW_DEFINE(PFUZE100_, name, reg, voltages, \ + pfuze100_sw_regulator_ops) + +#define PFUZE100_VGEN_DEFINE(name, reg, voltages) \ + PFUZE_DEFINE(PFUZE100_, name, reg, voltages, \ + pfuze100_ldo_regulator_ops) +/* SW1A */ +#define PFUZE100_SW1AVOL 32 +#define PFUZE100_SW1AVOL_VSEL 0 +#define PFUZE100_SW1AVOL_VSEL_M (0x3f<<0) + +#define PFUZE100_SW1ASTANDBY 33 +#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x0) +#define PFUZE100_SW1ASTANDBY_STBY_M (0x3f<<0) + +#define PFUZE100_SW1AOFF 34 +#define PFUZE100_SW1AOFF_OFF_VAL (0x0<<0) +#define PFUZE100_SW1AOFF_OFF_M (0x3f<<0) + +#define PFUZE100_SW1AMODE 35 +#define PFUZE100_SW1AMODE_OMODE_VAL (0x0<<5) +#define PFUZE100_SW1AMODE_OMODE_M (0x1<<5) +#define PFUZE100_SW1AMODE_MODE_VAL 0x7 /*Auto */ +#define PFUZE100_SW1AMODE_MODE_M (0xf<<0) + +#define PFUZE100_SW1ACON 36 +#define PFUZE100_SW1ACON_SPEED_VAL (0x1<<6) /*default */ +#define PFUZE100_SW1ACON_SPEED_M (0x3<<6) +#define PFUZE100_SW1ACON_PHASE_VAL (0x1<<4) /*default */ +#define PFUZE100_SW1ACON_PHASE_M (0x3<<4) +#define PFUZE100_SW1ACON_FREQ_VAL (0x1<<2) /*1Mhz */ +#define PFUZE100_SW1ACON_FREQ_M (0x3<<2) +#define PFUZE100_SW1ACON_LIM_VAL (0x0<<0) /*2Imax */ +#define PFUZE100_SW1ACON_LIM_M (0x3<<0) + +/*SW1B*/ +#define PFUZE100_SW1BVOL 39 +#define PFUZE100_SW1BVOL_VSEL 0 +#define PFUZE100_SW1BVOL_VSEL_M (0x3f<<0) + +#define PFUZE100_SW1BSTANDBY 40 +#define PFUZE100_SW1BSTANDBY_STBY_VAL 0x0 +#define PFUZE100_SW1BSTANDBY_STBY_M (0x3f<<0) + +#define PFUZE100_SW1BOFF 41 +#define PFUZE100_SW1BOFF_OFF_VAL 0x0 +#define PFUZE100_SW1BOFF_OFF_M (0x3f<<0) + +#define PFUZE100_SW1BMODE 42 +#define PFUZE100_SW1BMODE_OMODE_VAL (0x0<<5) +#define PFUZE100_SW1BMODE_OMODE_M (0x1<<5) +#define PFUZE100_SW1BMODE_MODE_VAL (0x7<<0) +#define PFUZE100_SW1BMODE_MODE_M (0xf<<0) + +#define PFUZE100_SW1BCON 43 +#define PFUZE100_SW1BCON_SPEED_VAL (0x1<<6) +#define PFUZE100_SW1BCON_SPEED_M (0x3<<6) +#define PFUZE100_SW1BCON_PHASE_VAL (0x1<<4) +#define PFUZE100_SW1BCON_PHASE_M (0x3<<4) +#define PFUZE100_SW1BCON_FREQ_VAL (0x1<<2) +#define PFUZE100_SW1BCON_FREQ_M (0x3<<2) +#define PFUZE100_SW1BCON_LIM_VAL (0x0<<0) +#define PFUZE100_SW1BCON_LIM_M (0x3<<0) + +/*SW1C*/ +#define PFUZE100_SW1CVOL 46 +#define PFUZE100_SW1CVOL_VSEL 0 +#define PFUZE100_SW1CVOL_VSEL_M (0x3f<<0) + +#define PFUZE100_SW1CSTANDBY 47 +#define PFUZE100_SW1CSTANDBY_STBY_VAL 0x0 +#define PFUZE100_SW1CSTANDBY_STBY_M (0x3f<<0) + +#define PFUZE100_SW1COFF 48 +#define PFUZE100_SW1COFF_OFF_VAL 0x0 +#define PFUZE100_SW1COFF_OFF_M (0x3f<<0) + +#define PFUZE100_SW1CMODE 49 +#define PFUZE100_SW1CMODE_OMODE_VAL (0x0<<5) +#define PFUZE100_SW1CMODE_OMODE_M (0x1<<5) +#define PFUZE100_SW1CMODE_MODE_VAL (0x7<<0) +#define PFUZE100_SW1CMODE_MODE_M (0xf<<0) + +#define PFUZE100_SW1CCON 50 +#define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) +#define PFUZE100_SW1CCON_SPEED_M (0x3<<6) +#define PFUZE100_SW1CCON_PHASE_VAL (0x1<<4) +#define PFUZE100_SW1CCON_PHASE_M (0x3<<4) +#define PFUZE100_SW1CCON_FREQ_VAL (0x1<<2) +#define PFUZE100_SW1CCON_FREQ_M (0x3<<2) +#define PFUZE100_SW1CCON_LIM_VAL (0x0<<0) +#define PFUZE100_SW1CCON_LIM_M (0x3<<0) + +/*SW2*/ +#define PFUZE100_SW2VOL 53 +#define PFUZE100_SW2VOL_VSEL 0 +#define PFUZE100_SW2VOL_VSEL_M (0x3f<<0) + +#define PFUZE100_SW2STANDBY 54 +#define PFUZE100_SW2STANDBY_STBY_VAL 0x0 +#define PFUZE100_SW2STANDBY_STBY_M (0x3f<<0) + +#define PFUZE100_SW2OFF 55 +#define PFUZE100_SW2OFF_OFF_VAL 0x0 +#define PFUZE100_SW2OFF_OFF_M (0x7f<<0) + +#define PFUZE100_SW2MODE 56 +#define PFUZE100_SW2MODE_OMODE_VAL (0x0<<5) +#define PFUZE100_SW2MODE_OMODE_M (0x1<<5) +#define PFUZE100_SW2MODE_MODE_VAL (0x7<<0) +#define PFUZE100_SW2MODE_MODE_M (0xf<<0) + +#define PFUZE100_SW2CON 57 +#define PFUZE100_SW2CON_SPEED_VAL (0x1<<6) +#define PFUZE100_SW2CON_SPEED_M (0x3<<6) +#define PFUZE100_SW2CON_PHASE_VAL (0x1<<4) +#define PFUZE100_SW2CON_PHASE_M (0x3<<4) +#define PFUZE100_SW2CON_FREQ_VAL (0x1<<2) +#define PFUZE100_SW2CON_FREQ_M (0x3<<2) +#define PFUZE100_SW2CON_LIM_VAL (0x0<<0) +#define PFUZE100_SW2CON_LIM_M (0x3<<0) + +/*SW3A*/ +#define PFUZE100_SW3AVOL 60 +#define PFUZE100_SW3AVOL_VSEL 0 +#define PFUZE100_SW3AVOL_VSEL_M (0x3f<<0) + +#define PFUZE100_SW3ASTANDBY 61 +#define PFUZE100_SW3ASTANDBY_STBY_VAL 0x0 +#define PFUZE100_SW3ASTANDBY_STBY_M (0x3f<<0) + +#define PFUZE100_SW3AOFF 62 +#define PFUZE100_SW3AOFF_OFF_VAL 0x0 +#define PFUZE100_SW3AOFF_OFF_M (0x3f<<0) + +#define PFUZE100_SW3AMODE 63 +#define PFUZE100_SW3AMODE_OMODE_VAL (0x0<<5) +#define PFUZE100_SW3AMODE_OMODE_M (0x1<<5) +#define PFUZE100_SW3AMODE_MODE_VAL (0x7<<0) +#define PFUZE100_SW3AMODE_MODE_M (0xf<<0) + +#define PFUZE100_SW3ACON 64 +#define PFUZE100_SW3ACON_SPEED_VAL (0x1<<6) +#define PFUZE100_SW3ACON_SPEED_M (0x3<<6) +#define PFUZE100_SW3ACON_PHASE_VAL (0x1<<4) +#define PFUZE100_SW3ACON_PHASE_M (0x3<<4) +#define PFUZE100_SW3ACON_FREQ_VAL (0x1<<2) +#define PFUZE100_SW3ACON_FREQ_M (0x3<<2) +#define PFUZE100_SW3ACON_LIM_VAL (0x0<<0) +#define PFUZE100_SW3ACON_LIM_M (0x3<<0) + +/*SW3B*/ +#define PFUZE100_SW3BVOL 67 +#define PFUZE100_SW3BVOL_VSEL 0 +#define PFUZE100_SW3BVOL_VSEL_M (0x3f<<0) + +#define PFUZE100_SW3BSTANDBY 68 +#define PFUZE100_SW3BSTANDBY_STBY_VAL 0x0 +#define PFUZE100_SW3BSTANDBY_STBY_M (0x3f<<0) + +#define PFUZE100_SW3BOFF 69 +#define PFUZE100_SW3BOFF_OFF_VAL 0x0 +#define PFUZE100_SW3BOFF_OFF_M (0x3f<<0) + +#define PFUZE100_SW3BMODE 70 +#define PFUZE100_SW3BMODE_OMODE_VAL (0x0<<5) +#define PFUZE100_SW3BMODE_OMODE_M (0x1<<5) +#define PFUZE100_SW3BMODE_MODE_VAL (0x7<<0) +#define PFUZE100_SW3BMODE_MODE_M (0xf<<0) + +#define PFUZE100_SW3BCON 71 +#define PFUZE100_SW3BCON_SPEED_VAL (0x1<<6) +#define PFUZE100_SW3BCON_SPEED_M (0x3<<6) +#define PFUZE100_SW3BCON_PHASE_VAL (0x1<<4) +#define PFUZE100_SW3BCON_PHASE_M (0x3<<4) +#define PFUZE100_SW3BCON_FREQ_VAL (0x1<<2) +#define PFUZE100_SW3BCON_FREQ_M (0x3<<2) +#define PFUZE100_SW3BCON_LIM_VAL (0x0<<0) +#define PFUZE100_SW3BCON_LIM_M (0x3<<0) + +/*SW4*/ +#define PFUZE100_SW4VOL 74 +#define PFUZE100_SW4VOL_VSEL 0 +#define PFUZE100_SW4VOL_VSEL_M (0x3f<<0) + +#define PFUZE100_SW4STANDBY 75 +#define PFUZE100_SW4STANDBY_STBY_VAL 0 +#define PFUZE100_SW4STANDBY_STBY_M (0x3f<<0) + +#define PFUZE100_SW4OFF 76 +#define PFUZE100_SW4OFF_OFF_VAL 0x0 +#define PFUZE100_SW4OFF_OFF_M (0x3f<<0) + +#define PFUZE100_SW4MODE 77 +#define PFUZE100_SW4MODE_OMODE_VAL (0x0<<5) +#define PFUZE100_SW4MODE_OMODE_M (0x1<<5) +#define PFUZE100_SW4MODE_MODE_VAL (0x7<<0) +#define PFUZE100_SW4MODE_MODE_M (0xf<<0) + +#define PFUZE100_SW4CON 78 +#define PFUZE100_SW4CON_SPEED_VAL (0x1<<6) +#define PFUZE100_SW4CON_SPEED_M (0x3<<6) +#define PFUZE100_SW4CON_PHASE_VAL (0x1<<4) +#define PFUZE100_SW4CON_PHASE_M (0x3<<4) +#define PFUZE100_SW4CON_FREQ_VAL (0x1<<2) +#define PFUZE100_SW4CON_FREQ_M (0x3<<2) +#define PFUZE100_SW4CON_LIM_VAL (0x0<<0) +#define PFUZE100_SW4CON_LIM_M (0x3<<0) + + /*SWBST*/ +#define PFUZE100_SWBSTCON1 102 +#define PFUZE100_SWBSTCON1_STBY_VAL 0x0 +#define PFUZE100_SWBSTCON1_STBY_M (0x3<<5) +#define PFUZE100_SWBSTCON1_SWBSTMOD_VAL (0x1<<2) +#define PFUZE100_SWBSTCON1_SWBSTMOD_M (0x3<<2) +#define PFUZE100_SWBSTCON1_VSEL 0 +#define PFUZE100_SWBSTCON1_VSEL_M (0x3<<0) + /*VREFDDR*/ +#define PFUZE100_VREFDDRCON 106 +#define PFUZE100_VREFDDRCON_EN (0x1<<4) + /*VSNVS*/ +#define PFUZE100_VSNVSVOL 107 +#define PFUZE100_VSNVSVOL_VSEL 0 +#define PFUZE100_VSNVSVOL_VSEL_M (0x3<<0) +/*VGEN1*/ +#define PFUZE100_VGEN1VOL 108 +#define PFUZE100_VGEN1VOL_STBY_VAL 0x0 +#define PFUZE100_VGEN1VOL_STBY_M (0x1<<5) +#define PFUZE100_VGEN1VOL_EN (0x1<<4) +#define PFUZE100_VGEN1VOL_VSEL 0 +#ifdef PFUZE100_FIRST_VERSION +#define PFUZE100_VGEN1VOL_VSEL_M (0x7<<0) +#else +#define PFUZE100_VGEN1VOL_VSEL_M (0xf<<0) +#endif +/*VGEN2*/ +#define PFUZE100_VGEN2VOL 109 +#define PFUZE100_VGEN2VOL_STBY_VAL 0x0 +#define PFUZE100_VGEN2VOL_STBY_M (0x1<<5) +#define PFUZE100_VGEN2VOL_EN (0x1<<4) +#define PFUZE100_VGEN2VOL_VSEL 0 +#ifdef PFUZE100_FIRST_VERSION +#define PFUZE100_VGEN2VOL_VSEL_M (0x7<<0) +#else +#define PFUZE100_VGEN2VOL_VSEL_M (0xf<<0) +#endif +/*VGEN3*/ +#define PFUZE100_VGEN3VOL 110 +#define PFUZE100_VGEN3VOL_STBY_VAL 0x0 +#define PFUZE100_VGEN3VOL_STBY_M (0x1<<5) +#define PFUZE100_VGEN3VOL_EN (0x1<<4) +#define PFUZE100_VGEN3VOL_VSEL 0 +#define PFUZE100_VGEN3VOL_VSEL_M (0xf<<0) +/*VGEN4*/ +#define PFUZE100_VGEN4VOL 111 +#define PFUZE100_VGEN4VOL_STBY_VAL 0x0 +#define PFUZE100_VGEN4VOL_STBY_M (0x1<<5) +#define PFUZE100_VGEN4VOL_EN (0x1<<4) +#define PFUZE100_VGEN4VOL_VSEL 0 +#define PFUZE100_VGEN4VOL_VSEL_M (0xf<<0) +/*VGEN5*/ +#define PFUZE100_VGEN5VOL 112 +#define PFUZE100_VGEN5VOL_STBY_VAL 0x0 +#define PFUZE100_VGEN5VOL_STBY_M (0x1<<5) +#define PFUZE100_VGEN5VOL_EN (0x1<<4) +#define PFUZE100_VGEN5VOL_VSEL 0 +#define PFUZE100_VGEN5VOL_VSEL_M (0xf<<0) +/*VGEN6*/ +#define PFUZE100_VGEN6VOL 113 +#define PFUZE100_VGEN6VOL_STBY_VAL 0x0 +#define PFUZE100_VGEN6VOL_STBY_M (0x1<<5) +#define PFUZE100_VGEN6VOL_EN (0x1<<4) +#define PFUZE100_VGEN6VOL_VSEL 0 +#define PFUZE100_VGEN6VOL_VSEL_M (0xf<<0) +static struct pfuze_regulator pfuze100_regulators[] = { + PFUZE100_SW_DEFINE(SW1A, SW1AVOL, pfuze100_sw1), + PFUZE100_SW_DEFINE(SW1B, SW1BVOL, pfuze100_sw1), + PFUZE100_SW_DEFINE(SW1C, SW1CVOL, pfuze100_sw1), + PFUZE100_SW_DEFINE(SW2, SW2VOL, pfuze100_sw2), + PFUZE100_SW_DEFINE(SW3A, SW3AVOL, pfuze100_sw3), + PFUZE100_SW_DEFINE(SW3B, SW3BVOL, pfuze100_sw3), + PFUZE100_SW_DEFINE(SW4, SW4VOL, pfuze100_sw4), + PFUZE100_SW_DEFINE(SWBST, SWBSTCON1, pfuze100_swbst), + PFUZE100_SW_DEFINE(VSNVS, VSNVSVOL, pfuze100_vsnvs), + PFUZE100_FIXED_VOL_DEFINE(VREFDDR, VREFDDRCON, pfuze100_vrefddr), + PFUZE100_VGEN_DEFINE(VGEN1, VGEN1VOL, pfuze100_vgen12), + PFUZE100_VGEN_DEFINE(VGEN2, VGEN2VOL, pfuze100_vgen12), + PFUZE100_VGEN_DEFINE(VGEN3, VGEN3VOL, pfuze100_vgen36), + PFUZE100_VGEN_DEFINE(VGEN4, VGEN4VOL, pfuze100_vgen36), + PFUZE100_VGEN_DEFINE(VGEN5, VGEN5VOL, pfuze100_vgen36), + PFUZE100_VGEN_DEFINE(VGEN6, VGEN6VOL, pfuze100_vgen36), +}; + +static int pfuze100_regulator_enable(struct regulator_dev *rdev) +{ + struct pfuze_regulator_priv *priv = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + int ret; + + dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); + pfuze_lock(priv->pfuze); + ret = pfuze_reg_rmw(priv->pfuze, pfuze100_regulators[id].reg, + pfuze100_regulators[id].enable_bit, + pfuze100_regulators[id].enable_bit); + pfuze_unlock(priv->pfuze); + return ret; +} + +static int pfuze100_regulator_disable(struct regulator_dev *rdev) +{ + struct pfuze_regulator_priv *priv = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + int ret; + + dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); + pfuze_lock(priv->pfuze); + ret = pfuze_reg_rmw(priv->pfuze, pfuze100_regulators[id].reg, + pfuze100_regulators[id].enable_bit, 0); + pfuze_unlock(priv->pfuze); + return ret; +} + +static int pfuze100_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct pfuze_regulator_priv *priv = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + int ret; + unsigned char val; + + pfuze_lock(priv->pfuze); + ret = pfuze_reg_read(priv->pfuze, pfuze100_regulators[id].reg, &val); + pfuze_unlock(priv->pfuze); + if (ret) + return ret; + dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); + return (val & pfuze100_regulators[id].enable_bit) != 0; +} + +int pfuze100_regulator_list_voltage(struct regulator_dev *rdev, + unsigned selector) +{ + int id = rdev_get_id(rdev); + + if (selector >= pfuze100_regulators[id].desc.n_voltages) + return -EINVAL; + return pfuze100_regulators[id].voltages[selector]; +} + +int pfuze100_get_best_voltage_index(struct regulator_dev *rdev, int min_uV, + int max_uV) +{ + int reg_id = rdev_get_id(rdev); + int i, bestmatch, bestindex; + + bestmatch = INT_MAX; + bestindex = -1; + for (i = 0; i < pfuze100_regulators[reg_id].desc.n_voltages; i++) { + if (pfuze100_regulators[reg_id].voltages[i] >= min_uV && + pfuze100_regulators[reg_id].voltages[i] < bestmatch) { + bestmatch = pfuze100_regulators[reg_id].voltages[i]; + bestindex = i; + } + } + if (bestindex < 0 || bestmatch > max_uV) { + dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n", + min_uV, max_uV); + return -EINVAL; + } + return bestindex; +} + +EXPORT_SYMBOL_GPL(pfuze100_get_best_voltage_index); + +static int +pfuze100_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, + int max_uV, unsigned *selector) +{ + + struct pfuze_regulator_priv *priv = rdev_get_drvdata(rdev); + int value, id = rdev_get_id(rdev); + int ret; + + dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", + __func__, id, min_uV, max_uV); + /* Find the best index */ + value = pfuze100_get_best_voltage_index(rdev, min_uV, max_uV); + dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value); + if (value < 0) + return value; + pfuze_lock(priv->pfuze); + ret = pfuze_reg_rmw(priv->pfuze, pfuze100_regulators[id].reg, + pfuze100_regulators[id].vsel_mask, + value << pfuze100_regulators[id].vsel_shift); + pfuze_unlock(priv->pfuze); + return ret; + +} + +static int pfuze100_regulator_get_voltage(struct regulator_dev *rdev) +{ + struct pfuze_regulator_priv *priv = rdev_get_drvdata(rdev); + int ret, id = rdev_get_id(rdev); + unsigned char val; + + dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); + pfuze_lock(priv->pfuze); + ret = pfuze_reg_read(priv->pfuze, pfuze100_regulators[id].reg, &val); + pfuze_unlock(priv->pfuze); + if (ret) + return ret; + val = (val & pfuze100_regulators[id].vsel_mask) + >> pfuze100_regulators[id].vsel_shift; + dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); + BUG_ON(val > pfuze100_regulators[id].desc.n_voltages); + return pfuze100_regulators[id].voltages[val]; +} + +static struct regulator_ops pfuze100_ldo_regulator_ops = { + .enable = pfuze100_regulator_enable, + .disable = pfuze100_regulator_disable, + .is_enabled = pfuze100_regulator_is_enabled, + .list_voltage = pfuze100_regulator_list_voltage, + .set_voltage = pfuze100_regulator_set_voltage, + .get_voltage = pfuze100_regulator_get_voltage, +}; + +static int pfuze100_fixed_regulator_set_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, + unsigned *selector) +{ + int id = rdev_get_id(rdev); + + dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", + __func__, id, min_uV, max_uV); + if (min_uV >= pfuze100_regulators[id].voltages[0] && + max_uV <= pfuze100_regulators[id].voltages[0]) + return 0; + else + return -EINVAL; + +} + +static int pfuze100_fixed_regulator_get_voltage(struct regulator_dev *rdev) +{ + int id = rdev_get_id(rdev); + + dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); + return pfuze100_regulators[id].voltages[0]; +} + +static struct regulator_ops pfuze100_fixed_regulator_ops = { + .enable = pfuze100_regulator_enable, + .disable = pfuze100_regulator_disable, + .is_enabled = pfuze100_regulator_is_enabled, + .set_voltage = pfuze100_fixed_regulator_set_voltage, + .get_voltage = pfuze100_fixed_regulator_get_voltage, +}; + +static int pfuze100_sw_regulator_is_enabled(struct regulator_dev *rdev) +{ + return 1; +} + +static struct regulator_ops pfuze100_sw_regulator_ops = { + .is_enabled = pfuze100_sw_regulator_is_enabled, + .list_voltage = pfuze100_regulator_list_voltage, + .set_voltage = pfuze100_regulator_set_voltage, + .get_voltage = pfuze100_regulator_get_voltage, +}; + +static int __devinit pfuze100_regulator_probe(struct platform_device *pdev) +{ + struct pfuze_regulator_priv *priv; + struct mc_pfuze *pfuze100 = dev_get_drvdata(pdev->dev.parent); + struct pfuze_regulator_platform_data *pdata = + dev_get_platdata(&pdev->dev); + struct pfuze_regulator_init_data *init_data; + int i, ret; + struct regulator *test_regulator; + + priv = kzalloc(sizeof(*priv) + + pdata->num_regulators * sizeof(priv->regulators[0]), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + priv->pfuze_regulators = pfuze100_regulators; + priv->pfuze = pfuze100; + pfuze_lock(pfuze100); + ret = pfuze_reg_rmw(pfuze100, PFUZE100_SWBSTCON1, + PFUZE100_SWBSTCON1_SWBSTMOD_M, + PFUZE100_SWBSTCON1_SWBSTMOD_VAL); + if (ret) + goto err_free; + pfuze_unlock(pfuze100); + for (i = 0; i < pdata->num_regulators; i++) { + init_data = &pdata->regulators[i]; + priv->regulators[i] = + regulator_register(&pfuze100_regulators[init_data->id].desc, + &pdev->dev, init_data->init_data, priv); + if (IS_ERR(priv->regulators[i])) { + dev_err(&pdev->dev, "failed to register regulator %s\n", + pfuze100_regulators[i].desc.name); + ret = PTR_ERR(priv->regulators[i]); + goto err; + } + } +#if 0 + test_regulator = regulator_get(&pdev->dev, "P1V325_VDDARM_SW1AB"); + if (test_regulator) + regulator_set_voltage(test_regulator, 1325000, 1325000); + test_regulator = regulator_get(&pdev->dev, "P1V325_VDDSOC_SW1C"); + if (test_regulator) + regulator_set_voltage(test_regulator, 1325000, 1325000); + test_regulator = regulator_get(&pdev->dev, "P3V0_VDDHIGH_SW2"); + if (test_regulator) + regulator_set_voltage(test_regulator, 3000000, 3000000); + test_regulator = regulator_get(&pdev->dev, "P1V5_DDR_SW3"); + if (test_regulator) + regulator_set_voltage(test_regulator, 1500000, 1500000); + test_regulator = regulator_get(&pdev->dev, "P1V8_SW4"); + if (test_regulator) + regulator_set_voltage(test_regulator, 1800000, 1800000); + test_regulator = regulator_get(&pdev->dev, "P5V0_SWBST"); + if (test_regulator) + regulator_set_voltage(test_regulator, 5000000, 5000000); + test_regulator = regulator_get(&pdev->dev, "P3V0_STBY"); + if (test_regulator) + regulator_set_voltage(test_regulator, 3000000, 3000000); + test_regulator = regulator_get(&pdev->dev, "P1V2_VGEN1"); + if (test_regulator) { + regulator_set_voltage(test_regulator, 1200000, 1200000); + regulator_enable(test_regulator); + } + test_regulator = regulator_get(&pdev->dev, "P1V5_VGEN2"); + if (test_regulator) { + regulator_set_voltage(test_regulator, 1500000, 1500000); + regulator_enable(test_regulator); + } + test_regulator = regulator_get(&pdev->dev, "P1V8_VGEN3"); + if (test_regulator) { + regulator_set_voltage(test_regulator, 1800000, 1800000); + regulator_enable(test_regulator); + } + test_regulator = regulator_get(&pdev->dev, "P1V8_VGEN4"); + if (test_regulator) { + regulator_set_voltage(test_regulator, 1800000, 1800000); + regulator_enable(test_regulator); + } + test_regulator = regulator_get(&pdev->dev, "P2V5_VGEN5"); + if (test_regulator) { + regulator_set_voltage(test_regulator, 2500000, 2500000); + regulator_enable(test_regulator); + } + test_regulator = regulator_get(&pdev->dev, "P2V8_VGEN6"); + if (test_regulator) { + regulator_set_voltage(test_regulator, 2800000, 2800000); + regulator_enable(test_regulator); + } +#endif + + platform_set_drvdata(pdev, priv); + return 0; +err: + while (--i >= 0) + regulator_unregister(priv->regulators[i]); +err_free: + pfuze_unlock(pfuze100); + kfree(priv); + return ret; +} + +static int __devexit pfuze100_regulator_remove(struct platform_device *pdev) +{ + struct pfuze_regulator_priv *priv = platform_get_drvdata(pdev); + struct pfuze_regulator_platform_data *pdata = + dev_get_platdata(&pdev->dev); + int i; + + platform_set_drvdata(pdev, NULL); + for (i = 0; i < pdata->num_regulators; i++) + regulator_unregister(priv->regulators[i]); + + kfree(priv); + return 0; +} + +static struct platform_driver pfuze100_regulator_driver = { + .driver = { + .name = "pfuze100-regulator", + .owner = THIS_MODULE, + }, + .remove = __devexit_p(pfuze100_regulator_remove), + .probe = pfuze100_regulator_probe, +}; + +static int __init pfuze100_regulator_init(void) +{ + return platform_driver_register(&pfuze100_regulator_driver); +} + +subsys_initcall(pfuze100_regulator_init); + +static void __exit pfuze100_regulator_exit(void) +{ + platform_driver_unregister(&pfuze100_regulator_driver); +} + +module_exit(pfuze100_regulator_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100 PMIC"); +MODULE_ALIAS("pfuze100-regulator");