-
Notifications
You must be signed in to change notification settings - Fork 6.1k
/
regulator_rpi_pico.c
158 lines (124 loc) · 4.98 KB
/
regulator_rpi_pico.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
* Copyright (c) 2023 TOKITA Hiroshi <tokita.hiroshi@fujitsu.com>
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT raspberrypi_core_supply_regulator
#include <zephyr/devicetree.h>
#include <zephyr/drivers/regulator.h>
#include <zephyr/dt-bindings/regulator/rpi_pico.h>
#include <zephyr/sys/linear_range.h>
#include <zephyr/toolchain.h>
#include <hardware/regs/vreg_and_chip_reset.h>
#include <hardware/structs/vreg_and_chip_reset.h>
static const struct linear_range core_ranges[] = {
LINEAR_RANGE_INIT(800000u, 0u, 0u, 5u),
LINEAR_RANGE_INIT(850000u, 50000u, 6u, 15u),
};
static const size_t num_core_ranges = ARRAY_SIZE(core_ranges);
struct regulator_rpi_pico_config {
struct regulator_common_config common;
vreg_and_chip_reset_hw_t * const reg;
const bool brown_out_detection;
const uint32_t brown_out_threshold;
};
struct regulator_rpi_pico_data {
struct regulator_common_data data;
};
/*
* APIs
*/
static unsigned int regulator_rpi_pico_count_voltages(const struct device *dev)
{
return linear_range_group_values_count(core_ranges, num_core_ranges);
}
static int regulator_rpi_pico_list_voltage(const struct device *dev, unsigned int idx,
int32_t *volt_uv)
{
return linear_range_group_get_value(core_ranges, num_core_ranges, idx, volt_uv);
}
static int regulator_rpi_pico_set_voltage(const struct device *dev, int32_t min_uv, int32_t max_uv)
{
const struct regulator_rpi_pico_config *config = dev->config;
uint16_t idx;
int ret;
ret = linear_range_group_get_win_index(core_ranges, num_core_ranges, min_uv, max_uv, &idx);
if (ret < 0) {
return ret;
}
config->reg->vreg = ((config->reg->vreg & ~VREG_AND_CHIP_RESET_VREG_VSEL_BITS) |
(idx << VREG_AND_CHIP_RESET_VREG_VSEL_LSB));
return 0;
}
static int regulator_rpi_pico_get_voltage(const struct device *dev, int32_t *volt_uv)
{
const struct regulator_rpi_pico_config *config = dev->config;
return linear_range_group_get_value(
core_ranges, num_core_ranges,
((config->reg->vreg & VREG_AND_CHIP_RESET_VREG_VSEL_BITS) >>
VREG_AND_CHIP_RESET_VREG_VSEL_LSB),
volt_uv);
}
static int regulator_rpi_pico_enable(const struct device *dev)
{
const struct regulator_rpi_pico_config *config = dev->config;
config->reg->vreg |= BIT(VREG_AND_CHIP_RESET_VREG_EN_LSB);
return 0;
}
static int regulator_rpi_pico_disable(const struct device *dev)
{
const struct regulator_rpi_pico_config *config = dev->config;
config->reg->vreg &= ~BIT(VREG_AND_CHIP_RESET_VREG_EN_LSB);
return 0;
}
static int regulator_rpi_pico_set_mode(const struct device *dev, regulator_mode_t mode)
{
const struct regulator_rpi_pico_config *config = dev->config;
if (mode & REGULATOR_RPI_PICO_MODE_HI_Z) {
config->reg->vreg |= REGULATOR_RPI_PICO_MODE_HI_Z;
} else {
config->reg->vreg &= (~REGULATOR_RPI_PICO_MODE_HI_Z);
}
return 0;
}
static int regulator_rpi_pico_get_mode(const struct device *dev, regulator_mode_t *mode)
{
const struct regulator_rpi_pico_config *config = dev->config;
*mode = (config->reg->vreg & REGULATOR_RPI_PICO_MODE_HI_Z);
return 0;
}
static int regulator_rpi_pico_init(const struct device *dev)
{
const struct regulator_rpi_pico_config *config = dev->config;
if (config->brown_out_detection) {
config->reg->bod =
(BIT(VREG_AND_CHIP_RESET_BOD_EN_LSB) |
(config->brown_out_threshold << VREG_AND_CHIP_RESET_BOD_VSEL_LSB));
} else {
config->reg->bod &= ~BIT(VREG_AND_CHIP_RESET_BOD_EN_LSB);
}
regulator_common_data_init(dev);
return regulator_common_init(dev, true);
}
static const struct regulator_driver_api api = {
.enable = regulator_rpi_pico_enable,
.disable = regulator_rpi_pico_disable,
.count_voltages = regulator_rpi_pico_count_voltages,
.list_voltage = regulator_rpi_pico_list_voltage,
.set_voltage = regulator_rpi_pico_set_voltage,
.get_voltage = regulator_rpi_pico_get_voltage,
.set_mode = regulator_rpi_pico_set_mode,
.get_mode = regulator_rpi_pico_get_mode,
};
#define REGULATOR_RPI_PICO_DEFINE_ALL(inst) \
static struct regulator_rpi_pico_data data_##inst; \
\
static const struct regulator_rpi_pico_config config_##inst = { \
.common = REGULATOR_DT_COMMON_CONFIG_INIT(inst), \
.reg = (vreg_and_chip_reset_hw_t * const)DT_INST_REG_ADDR(inst), \
.brown_out_detection = DT_INST_PROP(inst, raspberrypi_brown_out_detection), \
.brown_out_threshold = DT_INST_ENUM_IDX(inst, raspberrypi_brown_out_threshold), \
}; \
\
DEVICE_DT_INST_DEFINE(inst, regulator_rpi_pico_init, NULL, &data_##inst, &config_##inst, \
POST_KERNEL, CONFIG_REGULATOR_RPI_PICO_INIT_PRIORITY, &api);
DT_INST_FOREACH_STATUS_OKAY(REGULATOR_RPI_PICO_DEFINE_ALL)