Home | History | Annotate | Download | only in pmic
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2018
      4  * Lukasz Majewski, DENX Software Engineering, lukma (at) denx.de
      5  *
      6  */
      7 
      8 #include <common.h>
      9 #include <dm.h>
     10 #include <errno.h>
     11 #include <fsl_pmic.h>
     12 #include <i2c.h>
     13 #include <power/pmic.h>
     14 
     15 DECLARE_GLOBAL_DATA_PTR;
     16 
     17 static int mc34708_reg_count(struct udevice *dev)
     18 {
     19 	return PMIC_NUM_OF_REGS;
     20 }
     21 
     22 static int mc34708_write(struct udevice *dev, uint reg, const u8 *buff,
     23 			 int len)
     24 {
     25 	u8 buf[3] = { 0 };
     26 	int ret;
     27 
     28 	if (len != MC34708_TRANSFER_SIZE)
     29 		return -EINVAL;
     30 
     31 	/*
     32 	 * The MC34708 sends data with big endian format, hence we need to
     33 	 * perform manual byte swap.
     34 	 */
     35 	buf[0] = buff[2];
     36 	buf[1] = buff[1];
     37 	buf[2] = buff[0];
     38 
     39 	ret = dm_i2c_write(dev, reg, buf, len);
     40 	if (ret)
     41 		printf("write error to device: %p register: %#x!", dev, reg);
     42 
     43 	return ret;
     44 }
     45 
     46 static int mc34708_read(struct udevice *dev, uint reg, u8 *buff, int len)
     47 {
     48 	u8 buf[3] = { 0 };
     49 	int ret;
     50 
     51 	if (len != MC34708_TRANSFER_SIZE)
     52 		return -EINVAL;
     53 
     54 	ret = dm_i2c_read(dev, reg, buf, len);
     55 	if (ret)
     56 		printf("read error from device: %p register: %#x!", dev, reg);
     57 
     58 	buff[0] = buf[2];
     59 	buff[1] = buf[1];
     60 	buff[2] = buf[0];
     61 
     62 	return ret;
     63 }
     64 
     65 static int mc34708_probe(struct udevice *dev)
     66 {
     67 	struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
     68 
     69 	priv->trans_len = MC34708_TRANSFER_SIZE;
     70 
     71 	/*
     72 	 * Handle PMIC Errata 37: APS mode not fully functional,
     73 	 * use explicit PWM or PFM instead
     74 	 */
     75 	pmic_clrsetbits(dev, MC34708_REG_SW12_OPMODE,
     76 			MC34708_SW1AMODE_MASK | MC34708_SW2MODE_MASK,
     77 			SW_MODE_PWMPWM | (SW_MODE_PWMPWM << 14u));
     78 
     79 	pmic_clrsetbits(dev, MC34708_REG_SW345_OPMODE,
     80 			MC34708_SW3MODE_MASK | MC34708_SW4AMODE_MASK |
     81 			MC34708_SW4BMODE_MASK | MC34708_SW5MODE_MASK,
     82 			SW_MODE_PWMPWM | (SW_MODE_PWMPWM << 6u) |
     83 			(SW_MODE_PWMPWM << 12u) | (SW_MODE_PWMPWM << 18u));
     84 
     85 	return 0;
     86 }
     87 
     88 static struct dm_pmic_ops mc34708_ops = {
     89 	.reg_count = mc34708_reg_count,
     90 	.read	= mc34708_read,
     91 	.write	= mc34708_write,
     92 };
     93 
     94 static const struct udevice_id mc34708_ids[] = {
     95 	{ .compatible = "fsl,mc34708" },
     96 	{ }
     97 };
     98 
     99 U_BOOT_DRIVER(pmic_mc34708) = {
    100 	.name		= "mc34708_pmic",
    101 	.id		= UCLASS_PMIC,
    102 	.of_match	= mc34708_ids,
    103 	.probe          = mc34708_probe,
    104 	.ops		= &mc34708_ops,
    105 };
    106