File Index
Files and directories
Sign in
FILE

clk_and_regulator.c

File preview with syntax highlighting.

linux-6.19.14/drivers/platform/x86/intel/int3472/clk_and_regulator.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Author: Dan Scally <djrscally@gmail.com> */
  3
  4#include <linux/acpi.h>
  5#include <linux/clkdev.h>
  6#include <linux/clk-provider.h>
  7#include <linux/device.h>
  8#include <linux/gpio/consumer.h>
  9#include <linux/platform_data/x86/int3472.h>
 10#include <linux/regulator/driver.h>
 11#include <linux/slab.h>
 12
 13/*
 14 * 82c0d13a-78c5-4244-9bb1-eb8b539a8d11
 15 * This _DSM GUID allows controlling the sensor clk when it is not controlled
 16 * through a GPIO.
 17 */
 18static const guid_t img_clk_guid =
 19	GUID_INIT(0x82c0d13a, 0x78c5, 0x4244,
 20		  0x9b, 0xb1, 0xeb, 0x8b, 0x53, 0x9a, 0x8d, 0x11);
 21
 22static void skl_int3472_enable_clk(struct int3472_clock *clk, int enable)
 23{
 24	struct int3472_discrete_device *int3472 = to_int3472_device(clk);
 25	union acpi_object args[3];
 26	union acpi_object argv4;
 27
 28	if (clk->ena_gpio) {
 29		gpiod_set_value_cansleep(clk->ena_gpio, enable);
 30		return;
 31	}
 32
 33	args[0].integer.type = ACPI_TYPE_INTEGER;
 34	args[0].integer.value = clk->imgclk_index;
 35	args[1].integer.type = ACPI_TYPE_INTEGER;
 36	args[1].integer.value = enable;
 37	args[2].integer.type = ACPI_TYPE_INTEGER;
 38	args[2].integer.value = 1;
 39
 40	argv4.type = ACPI_TYPE_PACKAGE;
 41	argv4.package.count = 3;
 42	argv4.package.elements = args;
 43
 44	acpi_evaluate_dsm(acpi_device_handle(int3472->adev), &img_clk_guid,
 45			  0, 1, &argv4);
 46}
 47
 48/*
 49 * The regulators have to have .ops to be valid, but the only ops we actually
 50 * support are .enable and .disable which are handled via .ena_gpiod. Pass an
 51 * empty struct to clear the check without lying about capabilities.
 52 */
 53static const struct regulator_ops int3472_gpio_regulator_ops;
 54
 55static int skl_int3472_clk_prepare(struct clk_hw *hw)
 56{
 57	skl_int3472_enable_clk(to_int3472_clk(hw), 1);
 58	return 0;
 59}
 60
 61static void skl_int3472_clk_unprepare(struct clk_hw *hw)
 62{
 63	skl_int3472_enable_clk(to_int3472_clk(hw), 0);
 64}
 65
 66static int skl_int3472_clk_enable(struct clk_hw *hw)
 67{
 68	/*
 69	 * We're just turning a GPIO on to enable the clock, which operation
 70	 * has the potential to sleep. Given .enable() cannot sleep, but
 71	 * .prepare() can, we toggle the GPIO in .prepare() instead. Thus,
 72	 * nothing to do here.
 73	 */
 74	return 0;
 75}
 76
 77static void skl_int3472_clk_disable(struct clk_hw *hw)
 78{
 79	/* Likewise, nothing to do here... */
 80}
 81
 82static unsigned int skl_int3472_get_clk_frequency(struct int3472_discrete_device *int3472)
 83{
 84	union acpi_object *obj;
 85	unsigned int freq;
 86
 87	obj = skl_int3472_get_acpi_buffer(int3472->sensor, "SSDB");
 88	if (IS_ERR(obj))
 89		return 0; /* report rate as 0 on error */
 90
 91	if (obj->buffer.length < CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET + sizeof(u32)) {
 92		dev_err(int3472->dev, "The buffer is too small\n");
 93		kfree(obj);
 94		return 0;
 95	}
 96
 97	freq = *(u32 *)(obj->buffer.pointer + CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET);
 98
 99	kfree(obj);
100	return freq;
101}
102
103static unsigned long skl_int3472_clk_recalc_rate(struct clk_hw *hw,
104						 unsigned long parent_rate)
105{
106	struct int3472_clock *clk = to_int3472_clk(hw);
107
108	return clk->frequency;
109}
110
111static const struct clk_ops skl_int3472_clock_ops = {
112	.prepare = skl_int3472_clk_prepare,
113	.unprepare = skl_int3472_clk_unprepare,
114	.enable = skl_int3472_clk_enable,
115	.disable = skl_int3472_clk_disable,
116	.recalc_rate = skl_int3472_clk_recalc_rate,
117};
118
119static int skl_int3472_register_clock(struct int3472_discrete_device *int3472)
120{
121	struct acpi_device *adev = int3472->adev;
122	struct clk_init_data init = {
123		.ops = &skl_int3472_clock_ops,
124		.flags = CLK_GET_RATE_NOCACHE,
125	};
126	int ret;
127
128	init.name = kasprintf(GFP_KERNEL, "%s-clk", acpi_dev_name(adev));
129	if (!init.name)
130		return -ENOMEM;
131
132	int3472->clock.frequency = skl_int3472_get_clk_frequency(int3472);
133	int3472->clock.clk_hw.init = &init;
134	int3472->clock.clk = clk_register(&adev->dev, &int3472->clock.clk_hw);
135	if (IS_ERR(int3472->clock.clk)) {
136		ret = PTR_ERR(int3472->clock.clk);
137		goto out_free_init_name;
138	}
139
140	int3472->clock.cl = clkdev_create(int3472->clock.clk, NULL, int3472->sensor_name);
141	if (!int3472->clock.cl) {
142		ret = -ENOMEM;
143		goto err_unregister_clk;
144	}
145
146	kfree(init.name);
147	return 0;
148
149err_unregister_clk:
150	clk_unregister(int3472->clock.clk);
151out_free_init_name:
152	kfree(init.name);
153	return ret;
154}
155
156int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472)
157{
158	if (int3472->clock.cl)
159		return 0; /* A GPIO controlled clk has already been registered */
160
161	if (!acpi_check_dsm(int3472->adev->handle, &img_clk_guid, 0, BIT(1)))
162		return 0; /* DSM clock control is not available */
163
164	return skl_int3472_register_clock(int3472);
165}
166
167int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472,
168				    struct gpio_desc *gpio)
169{
170	if (int3472->clock.cl)
171		return -EBUSY;
172
173	int3472->clock.ena_gpio = gpio;
174
175	return skl_int3472_register_clock(int3472);
176}
177
178void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472)
179{
180	if (!int3472->clock.cl)
181		return;
182
183	clkdev_drop(int3472->clock.cl);
184	clk_unregister(int3472->clock.clk);
185	gpiod_put(int3472->clock.ena_gpio);
186}
187
188int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
189				   struct gpio_desc *gpio,
190				   unsigned int enable_time,
191				   const char *supply_name,
192				   const char *second_sensor)
193{
194	struct regulator_init_data init_data = { };
195	struct int3472_gpio_regulator *regulator;
196	struct regulator_config cfg = { };
197	int i, j;
198
199	if (int3472->n_regulator_gpios >= INT3472_MAX_REGULATORS) {
200		dev_err(int3472->dev, "Too many regulators mapped\n");
201		return -EINVAL;
202	}
203
204	if (strlen(supply_name) >= GPIO_SUPPLY_NAME_LENGTH) {
205		dev_err(int3472->dev, "supply-name '%s' length too long\n", supply_name);
206		return -E2BIG;
207	}
208
209	regulator = &int3472->regulators[int3472->n_regulator_gpios];
210	string_upper(regulator->supply_name_upper, supply_name);
211
212	/* The below code assume that map-count is 2 (upper- and lower-case) */
213	static_assert(GPIO_REGULATOR_SUPPLY_MAP_COUNT == 2);
214
215	for (i = 0, j = 0; i < GPIO_REGULATOR_SUPPLY_MAP_COUNT; i++) {
216		const char *supply = i ? regulator->supply_name_upper : supply_name;
217
218		regulator->supply_map[j].supply = supply;
219		regulator->supply_map[j].dev_name = int3472->sensor_name;
220		j++;
221
222		if (second_sensor) {
223			regulator->supply_map[j].supply = supply;
224			regulator->supply_map[j].dev_name = second_sensor;
225			j++;
226		}
227	}
228
229	init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
230	init_data.consumer_supplies = regulator->supply_map;
231	init_data.num_consumer_supplies = j;
232
233	snprintf(regulator->regulator_name, sizeof(regulator->regulator_name), "%s-%s",
234		 acpi_dev_name(int3472->adev), supply_name);
235
236	regulator->rdesc = INT3472_REGULATOR(regulator->regulator_name,
237					     &int3472_gpio_regulator_ops,
238					     enable_time, GPIO_REGULATOR_OFF_ON_DELAY);
239
240	cfg.dev = &int3472->adev->dev;
241	cfg.init_data = &init_data;
242	cfg.ena_gpiod = gpio;
243
244	regulator->rdev = regulator_register(int3472->dev, &regulator->rdesc, &cfg);
245	if (IS_ERR(regulator->rdev))
246		return PTR_ERR(regulator->rdev);
247
248	int3472->n_regulator_gpios++;
249	return 0;
250}
251
252void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472)
253{
254	for (int i = 0; i < int3472->n_regulator_gpios; i++)
255		regulator_unregister(int3472->regulators[i].rdev);
256}
~/ Read-only file preview.