1c2f74c8fSMateusz Kulikowski /* 2c2f74c8fSMateusz Kulikowski * Qualcomm pm8916 pmic driver 3c2f74c8fSMateusz Kulikowski * 4c2f74c8fSMateusz Kulikowski * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com> 5c2f74c8fSMateusz Kulikowski * 6c2f74c8fSMateusz Kulikowski * SPDX-License-Identifier: GPL-2.0+ 7c2f74c8fSMateusz Kulikowski */ 8c2f74c8fSMateusz Kulikowski #include <common.h> 9c2f74c8fSMateusz Kulikowski #include <dm.h> 10c2f74c8fSMateusz Kulikowski #include <dm/root.h> 11c2f74c8fSMateusz Kulikowski #include <power/pmic.h> 12c2f74c8fSMateusz Kulikowski #include <spmi/spmi.h> 13c2f74c8fSMateusz Kulikowski 14c2f74c8fSMateusz Kulikowski DECLARE_GLOBAL_DATA_PTR; 15c2f74c8fSMateusz Kulikowski 16c2f74c8fSMateusz Kulikowski #define PID_SHIFT 8 17c2f74c8fSMateusz Kulikowski #define PID_MASK (0xFF << PID_SHIFT) 18c2f74c8fSMateusz Kulikowski #define REG_MASK 0xFF 19c2f74c8fSMateusz Kulikowski 20c2f74c8fSMateusz Kulikowski struct pm8916_priv { 21*3bfc8152STom Rini uint32_t usid; /* Slave ID on SPMI bus */ 22c2f74c8fSMateusz Kulikowski }; 23c2f74c8fSMateusz Kulikowski 24c2f74c8fSMateusz Kulikowski static int pm8916_reg_count(struct udevice *dev) 25c2f74c8fSMateusz Kulikowski { 26c2f74c8fSMateusz Kulikowski return 0xFFFF; 27c2f74c8fSMateusz Kulikowski } 28c2f74c8fSMateusz Kulikowski 29c2f74c8fSMateusz Kulikowski static int pm8916_write(struct udevice *dev, uint reg, const uint8_t *buff, 30c2f74c8fSMateusz Kulikowski int len) 31c2f74c8fSMateusz Kulikowski { 32c2f74c8fSMateusz Kulikowski struct pm8916_priv *priv = dev_get_priv(dev); 33c2f74c8fSMateusz Kulikowski 34c2f74c8fSMateusz Kulikowski if (len != 1) 35c2f74c8fSMateusz Kulikowski return -EINVAL; 36c2f74c8fSMateusz Kulikowski 37c2f74c8fSMateusz Kulikowski return spmi_reg_write(dev->parent, priv->usid, 38c2f74c8fSMateusz Kulikowski (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK, 39c2f74c8fSMateusz Kulikowski *buff); 40c2f74c8fSMateusz Kulikowski } 41c2f74c8fSMateusz Kulikowski 42c2f74c8fSMateusz Kulikowski static int pm8916_read(struct udevice *dev, uint reg, uint8_t *buff, int len) 43c2f74c8fSMateusz Kulikowski { 44c2f74c8fSMateusz Kulikowski struct pm8916_priv *priv = dev_get_priv(dev); 45c2f74c8fSMateusz Kulikowski int val; 46c2f74c8fSMateusz Kulikowski 47c2f74c8fSMateusz Kulikowski if (len != 1) 48c2f74c8fSMateusz Kulikowski return -EINVAL; 49c2f74c8fSMateusz Kulikowski 50c2f74c8fSMateusz Kulikowski val = spmi_reg_read(dev->parent, priv->usid, 51c2f74c8fSMateusz Kulikowski (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK); 52c2f74c8fSMateusz Kulikowski 53c2f74c8fSMateusz Kulikowski if (val < 0) 54c2f74c8fSMateusz Kulikowski return val; 55c2f74c8fSMateusz Kulikowski *buff = val; 56c2f74c8fSMateusz Kulikowski return 0; 57c2f74c8fSMateusz Kulikowski } 58c2f74c8fSMateusz Kulikowski 59c2f74c8fSMateusz Kulikowski static struct dm_pmic_ops pm8916_ops = { 60c2f74c8fSMateusz Kulikowski .reg_count = pm8916_reg_count, 61c2f74c8fSMateusz Kulikowski .read = pm8916_read, 62c2f74c8fSMateusz Kulikowski .write = pm8916_write, 63c2f74c8fSMateusz Kulikowski }; 64c2f74c8fSMateusz Kulikowski 65c2f74c8fSMateusz Kulikowski static const struct udevice_id pm8916_ids[] = { 66c2f74c8fSMateusz Kulikowski { .compatible = "qcom,spmi-pmic" }, 67c2f74c8fSMateusz Kulikowski { } 68c2f74c8fSMateusz Kulikowski }; 69c2f74c8fSMateusz Kulikowski 70c2f74c8fSMateusz Kulikowski static int pm8916_probe(struct udevice *dev) 71c2f74c8fSMateusz Kulikowski { 72c2f74c8fSMateusz Kulikowski struct pm8916_priv *priv = dev_get_priv(dev); 73c2f74c8fSMateusz Kulikowski 74c2f74c8fSMateusz Kulikowski priv->usid = dev_get_addr(dev); 75c2f74c8fSMateusz Kulikowski 76c2f74c8fSMateusz Kulikowski if (priv->usid == FDT_ADDR_T_NONE) 77c2f74c8fSMateusz Kulikowski return -EINVAL; 78c2f74c8fSMateusz Kulikowski 79c2f74c8fSMateusz Kulikowski return 0; 80c2f74c8fSMateusz Kulikowski } 81c2f74c8fSMateusz Kulikowski 82c2f74c8fSMateusz Kulikowski 83c2f74c8fSMateusz Kulikowski static int pm8916_bind(struct udevice *dev) 84c2f74c8fSMateusz Kulikowski { 85c2f74c8fSMateusz Kulikowski return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); 86c2f74c8fSMateusz Kulikowski } 87c2f74c8fSMateusz Kulikowski 88c2f74c8fSMateusz Kulikowski U_BOOT_DRIVER(pmic_pm8916) = { 89c2f74c8fSMateusz Kulikowski .name = "pmic_pm8916", 90c2f74c8fSMateusz Kulikowski .id = UCLASS_PMIC, 91c2f74c8fSMateusz Kulikowski .of_match = pm8916_ids, 92c2f74c8fSMateusz Kulikowski .bind = pm8916_bind, 93c2f74c8fSMateusz Kulikowski .probe = pm8916_probe, 94c2f74c8fSMateusz Kulikowski .ops = &pm8916_ops, 95c2f74c8fSMateusz Kulikowski .priv_auto_alloc_size = sizeof(struct pm8916_priv), 96c2f74c8fSMateusz Kulikowski }; 97