cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clk_and_regulator.c (5550B)


      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/regulator/driver.h>
     10#include <linux/slab.h>
     11
     12#include "common.h"
     13
     14/*
     15 * The regulators have to have .ops to be valid, but the only ops we actually
     16 * support are .enable and .disable which are handled via .ena_gpiod. Pass an
     17 * empty struct to clear the check without lying about capabilities.
     18 */
     19static const struct regulator_ops int3472_gpio_regulator_ops;
     20
     21static int skl_int3472_clk_prepare(struct clk_hw *hw)
     22{
     23	struct int3472_gpio_clock *clk = to_int3472_clk(hw);
     24
     25	gpiod_set_value_cansleep(clk->ena_gpio, 1);
     26	gpiod_set_value_cansleep(clk->led_gpio, 1);
     27
     28	return 0;
     29}
     30
     31static void skl_int3472_clk_unprepare(struct clk_hw *hw)
     32{
     33	struct int3472_gpio_clock *clk = to_int3472_clk(hw);
     34
     35	gpiod_set_value_cansleep(clk->ena_gpio, 0);
     36	gpiod_set_value_cansleep(clk->led_gpio, 0);
     37}
     38
     39static int skl_int3472_clk_enable(struct clk_hw *hw)
     40{
     41	/*
     42	 * We're just turning a GPIO on to enable the clock, which operation
     43	 * has the potential to sleep. Given .enable() cannot sleep, but
     44	 * .prepare() can, we toggle the GPIO in .prepare() instead. Thus,
     45	 * nothing to do here.
     46	 */
     47	return 0;
     48}
     49
     50static void skl_int3472_clk_disable(struct clk_hw *hw)
     51{
     52	/* Likewise, nothing to do here... */
     53}
     54
     55static unsigned int skl_int3472_get_clk_frequency(struct int3472_discrete_device *int3472)
     56{
     57	union acpi_object *obj;
     58	unsigned int freq;
     59
     60	obj = skl_int3472_get_acpi_buffer(int3472->sensor, "SSDB");
     61	if (IS_ERR(obj))
     62		return 0; /* report rate as 0 on error */
     63
     64	if (obj->buffer.length < CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET + sizeof(u32)) {
     65		dev_err(int3472->dev, "The buffer is too small\n");
     66		kfree(obj);
     67		return 0;
     68	}
     69
     70	freq = *(u32 *)(obj->buffer.pointer + CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET);
     71
     72	kfree(obj);
     73	return freq;
     74}
     75
     76static unsigned long skl_int3472_clk_recalc_rate(struct clk_hw *hw,
     77						 unsigned long parent_rate)
     78{
     79	struct int3472_gpio_clock *clk = to_int3472_clk(hw);
     80
     81	return clk->frequency;
     82}
     83
     84static const struct clk_ops skl_int3472_clock_ops = {
     85	.prepare = skl_int3472_clk_prepare,
     86	.unprepare = skl_int3472_clk_unprepare,
     87	.enable = skl_int3472_clk_enable,
     88	.disable = skl_int3472_clk_disable,
     89	.recalc_rate = skl_int3472_clk_recalc_rate,
     90};
     91
     92int skl_int3472_register_clock(struct int3472_discrete_device *int3472)
     93{
     94	struct clk_init_data init = {
     95		.ops = &skl_int3472_clock_ops,
     96		.flags = CLK_GET_RATE_NOCACHE,
     97	};
     98	int ret;
     99
    100	init.name = kasprintf(GFP_KERNEL, "%s-clk",
    101			      acpi_dev_name(int3472->adev));
    102	if (!init.name)
    103		return -ENOMEM;
    104
    105	int3472->clock.frequency = skl_int3472_get_clk_frequency(int3472);
    106
    107	int3472->clock.clk_hw.init = &init;
    108	int3472->clock.clk = clk_register(&int3472->adev->dev,
    109					  &int3472->clock.clk_hw);
    110	if (IS_ERR(int3472->clock.clk)) {
    111		ret = PTR_ERR(int3472->clock.clk);
    112		goto out_free_init_name;
    113	}
    114
    115	int3472->clock.cl = clkdev_create(int3472->clock.clk, NULL,
    116					  int3472->sensor_name);
    117	if (!int3472->clock.cl) {
    118		ret = -ENOMEM;
    119		goto err_unregister_clk;
    120	}
    121
    122	kfree(init.name);
    123	return 0;
    124
    125err_unregister_clk:
    126	clk_unregister(int3472->clock.clk);
    127out_free_init_name:
    128	kfree(init.name);
    129
    130	return ret;
    131}
    132
    133void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472)
    134{
    135	clkdev_drop(int3472->clock.cl);
    136	clk_unregister(int3472->clock.clk);
    137}
    138
    139int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
    140				   struct acpi_resource_gpio *agpio)
    141{
    142	const struct int3472_sensor_config *sensor_config;
    143	char *path = agpio->resource_source.string_ptr;
    144	struct regulator_consumer_supply supply_map;
    145	struct regulator_init_data init_data = { };
    146	struct regulator_config cfg = { };
    147	int ret;
    148
    149	sensor_config = int3472->sensor_config;
    150	if (IS_ERR(sensor_config)) {
    151		dev_err(int3472->dev, "No sensor module config\n");
    152		return PTR_ERR(sensor_config);
    153	}
    154
    155	if (!sensor_config->supply_map.supply) {
    156		dev_err(int3472->dev, "No supply name defined\n");
    157		return -ENODEV;
    158	}
    159
    160	init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
    161	init_data.num_consumer_supplies = 1;
    162	supply_map = sensor_config->supply_map;
    163	supply_map.dev_name = int3472->sensor_name;
    164	init_data.consumer_supplies = &supply_map;
    165
    166	snprintf(int3472->regulator.regulator_name,
    167		 sizeof(int3472->regulator.regulator_name), "%s-regulator",
    168		 acpi_dev_name(int3472->adev));
    169	snprintf(int3472->regulator.supply_name,
    170		 GPIO_REGULATOR_SUPPLY_NAME_LENGTH, "supply-0");
    171
    172	int3472->regulator.rdesc = INT3472_REGULATOR(
    173						int3472->regulator.regulator_name,
    174						int3472->regulator.supply_name,
    175						&int3472_gpio_regulator_ops);
    176
    177	int3472->regulator.gpio = acpi_get_and_request_gpiod(path, agpio->pin_table[0],
    178							     "int3472,regulator");
    179	if (IS_ERR(int3472->regulator.gpio)) {
    180		dev_err(int3472->dev, "Failed to get regulator GPIO line\n");
    181		return PTR_ERR(int3472->regulator.gpio);
    182	}
    183
    184	cfg.dev = &int3472->adev->dev;
    185	cfg.init_data = &init_data;
    186	cfg.ena_gpiod = int3472->regulator.gpio;
    187
    188	int3472->regulator.rdev = regulator_register(&int3472->regulator.rdesc,
    189						     &cfg);
    190	if (IS_ERR(int3472->regulator.rdev)) {
    191		ret = PTR_ERR(int3472->regulator.rdev);
    192		goto err_free_gpio;
    193	}
    194
    195	return 0;
    196
    197err_free_gpio:
    198	gpiod_put(int3472->regulator.gpio);
    199
    200	return ret;
    201}
    202
    203void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472)
    204{
    205	regulator_unregister(int3472->regulator.rdev);
    206	gpiod_put(int3472->regulator.gpio);
    207}