blob: 4923255f0a7e71dddc3dd008b927f5e62003120c [file] [log] [blame]
Svyatoslav Ryhelcf77d732025-02-01 16:02:45 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
4 */
5
6#include <dm.h>
7#include <dm/lists.h>
8#include <log.h>
9#include <power/pmic.h>
10#include <power/cpcap.h>
11#include <spi.h>
12#include <linux/delay.h>
13#include <linux/err.h>
14
15static int cpcap_write(struct udevice *dev, uint reg, const uint8_t *buff, int len)
16{
17 u8 buf[4];
18 u16 data = *(u16 *)buff;
19 int ret;
20
21 buf[0] = ((reg >> 8) & 0xff) | 0x80;
22 buf[1] = reg & 0xff;
23 buf[2] = data >> 8 & 0xff;
24 buf[3] = data & 0xff;
25
26 ret = dm_spi_xfer(dev, 32, buf, NULL, SPI_XFER_ONCE);
27
28 log_debug("%s: reg 0x%x, data 0x%04x, ret %d\n", __func__, reg, data, ret);
29
30 return ret;
31}
32
33static int cpcap_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
34{
35 u8 buf[4];
36 int ret;
37
38 buf[0] = (reg >> 8) & 0xff;
39 buf[1] = reg & 0xff;
40 buf[2] = 0;
41 buf[3] = 0;
42
43 ret = dm_spi_xfer(dev, 32, buf, buf, SPI_XFER_ONCE);
44 *buff = (buf[2] << 8) | buf[3];
45
46 log_debug("%s: reg 0x%x, data 0x%04x, ret %d\n", __func__, reg, *buff, ret);
47 return ret;
48}
49
50static int cpcap_probe(struct udevice *dev)
51{
52 struct spi_slave *slave = dev_get_parent_priv(dev);
53 int ret;
54
55 ret = spi_claim_bus(slave);
56 if (ret) {
57 log_err("SPI bus allocation failed (%d)\n", ret);
58 return ret;
59 }
60
61 u16 id = pmic_reg_read(dev, CPCAP_REG_VERSC1);
62
63 u16 ven = (id >> 6) & 0x7;
64 u16 rev = ((id >> 3) & 0x7) | ((id << 3) & 0x38);
65
66 log_debug("%s: vendor %s rev: %i.%i (%x)\n", __func__,
67 ven == CPCAP_VENDOR_ST ? "ST" : "TI",
68 CPCAP_REVISION_MAJOR(rev), CPCAP_REVISION_MINOR(rev),
69 rev);
70 return 0;
71}
72
73static struct dm_pmic_ops cpcap_ops = {
74 .read = cpcap_read,
75 .write = cpcap_write,
76};
77
78static const struct udevice_id cpcap_ids[] = {
79 { .compatible = "motorola,cpcap" },
80 { .compatible = "st,6556002" },
81 { }
82};
83
84U_BOOT_DRIVER(pmic_cpcap) = {
85 .name = "cpcap_pmic",
86 .id = UCLASS_PMIC,
87 .of_match = cpcap_ids,
88 .probe = cpcap_probe,
89 .ops = &cpcap_ops,
90};