/* * Base driver for Marvell 88PM800 * * Copyright (C) 2012 Marvell International Ltd. * Haojian Zhuang <haojian.zhuang@marvell.com> * Joseph(Yossi) Hanin <yhanin@marvell.com> * Qiao Zhou <zhouqiao@marvell.com> * * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of this * archive for more details. * * 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
*/
staticint device_gpadc_init(struct pm80x_chip *chip, struct pm80x_platform_data *pdata)
{ struct pm80x_subchip *subchip = chip->subchip; struct regmap *map = subchip->regmap_gpadc; int data = 0, mask = 0, ret = 0;
if (!map) {
dev_warn(chip->dev, "Warning: gpadc regmap is not available!\n"); return -EINVAL;
} /* * initialize GPADC without activating it turn on GPADC * measurments
*/
ret = regmap_update_bits(map,
PM800_GPADC_MISC_CONFIG2,
PM800_GPADC_MISC_GPFSM_EN,
PM800_GPADC_MISC_GPFSM_EN); if (ret < 0) goto out; /* * This function configures the ADC as requires for * CP implementation.CP does not "own" the ADC configuration * registers and relies on AP. * Reason: enable automatic ADC measurements needed * for CP to get VBAT and RF temperature readings.
*/
ret = regmap_update_bits(map, PM800_GPADC_MEAS_EN1,
PM800_MEAS_EN1_VBAT, PM800_MEAS_EN1_VBAT); if (ret < 0) goto out;
ret = regmap_update_bits(map, PM800_GPADC_MEAS_EN2,
(PM800_MEAS_EN2_RFTMP | PM800_MEAS_GP0_EN),
(PM800_MEAS_EN2_RFTMP | PM800_MEAS_GP0_EN)); if (ret < 0) goto out;
/* * the defult of PM800 is GPADC operates at 100Ks/s rate * and Number of GPADC slots with active current bias prior * to GPADC sampling = 1 slot for all GPADCs set for * Temprature mesurmants
*/
mask = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 |
PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3);
if (pdata && (pdata->batt_det == 0))
data = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 |
PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3); else
data = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN2 |
PM800_GPADC_GP_BIAS_EN3);
ret = regmap_update_bits(map, PM800_GP_BIAS_ENA1, mask, data); if (ret < 0) goto out;
/* * alarm wake up bit will be clear in device_irq_init(), * read before that
*/
ret = regmap_read(chip->regmap, PM800_RTC_CONTROL, &val); if (ret < 0) {
dev_err(chip->dev, "Failed to read RTC register: %d\n", ret); goto out;
} if (val & PM800_ALARM_WAKEUP) { if (pdata && pdata->rtc)
pdata->rtc->rtc_wakeup = 1;
}
ret = device_gpadc_init(chip, pdata); if (ret < 0) {
dev_err(chip->dev, "[%s]Failed to init gpadc\n", __func__); goto out;
}
chip->regmap_irq_chip = &pm800_irq_chip;
ret = device_irq_init_800(chip); if (ret < 0) {
dev_err(chip->dev, "[%s]Failed to init pm800 irq\n", __func__); goto out;
}
ret = device_onkey_init(chip, pdata); if (ret) {
dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev;
}
ret = device_rtc_init(chip, pdata); if (ret) {
dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out;
}
ret = device_regulator_init(chip, pdata); if (ret) {
dev_err(chip->dev, "Failed to add regulators subdev\n"); goto out;
}
staticint pm800_probe(struct i2c_client *client)
{ int ret = 0; struct pm80x_chip *chip; struct pm80x_platform_data *pdata = dev_get_platdata(&client->dev); struct pm80x_subchip *subchip;
ret = pm80x_init(client); if (ret) {
dev_err(&client->dev, "pm800_init fail\n"); goto out_init;
}
chip = i2c_get_clientdata(client);
/* init subchip for PM800 */
subchip =
devm_kzalloc(&client->dev, sizeof(struct pm80x_subchip),
GFP_KERNEL); if (!subchip) {
ret = -ENOMEM; goto err_subchip_alloc;
}
/* pm800 has 2 addtional pages to support power and gpadc. */
subchip->power_page_addr = client->addr + 1;
subchip->gpadc_page_addr = client->addr + 2;
chip->subchip = subchip;
ret = pm800_pages_init(chip); if (ret) {
dev_err(&client->dev, "pm800_pages_init failed!\n"); goto err_device_init;
}
ret = device_800_init(chip, pdata); if (ret) {
dev_err(chip->dev, "Failed to initialize 88pm800 devices\n"); goto err_device_init;
}
if (pdata && pdata->plat_config)
pdata->plat_config(chip, pdata);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.