linux/drivers/soc/qcom/icc-bwmon.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
 * Copyright (C) 2021-2022 Linaro Ltd
 * Author: Krzysztof Kozlowski <[email protected]>, based on
 *         previous work of Thara Gopinath and msm-4.9 downstream sources.
 */

#include <linux/err.h>
#include <linux/interconnect.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/regmap.h>
#include <linux/sizes.h>

/*
 * The BWMON samples data throughput within 'sample_ms' time. With three
 * configurable thresholds (Low, Medium and High) gives four windows (called
 * zones) of current bandwidth:
 *
 * Zone 0: byte count < THRES_LO
 * Zone 1: THRES_LO < byte count < THRES_MED
 * Zone 2: THRES_MED < byte count < THRES_HIGH
 * Zone 3: THRES_HIGH < byte count
 *
 * Zones 0 and 2 are not used by this driver.
 */

/* Internal sampling clock frequency */
#define HW_TIMER_HZ

#define BWMON_V4_GLOBAL_IRQ_CLEAR
#define BWMON_V4_GLOBAL_IRQ_ENABLE
/*
 * All values here and further are matching regmap fields, so without absolute
 * register offsets.
 */
#define BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE

/*
 * Starting with SDM845, the BWMON4 register space has changed a bit:
 * the global registers were jammed into the beginning of the monitor region.
 * To keep the proper offsets, one would have to map <GLOBAL_BASE 0x200> and
 * <GLOBAL_BASE+0x100 0x300>, which is straight up wrong.
 * To facilitate for that, while allowing the older, arguably more proper
 * implementations to work, offset the global registers by -0x100 to avoid
 * having to map half of the global registers twice.
 */
#define BWMON_V4_845_OFFSET
#define BWMON_V4_GLOBAL_IRQ_CLEAR_845
#define BWMON_V4_GLOBAL_IRQ_ENABLE_845

#define BWMON_V4_IRQ_STATUS
#define BWMON_V4_IRQ_CLEAR

#define BWMON_V4_IRQ_ENABLE
#define BWMON_IRQ_ENABLE_MASK
#define BWMON_V5_IRQ_STATUS
#define BWMON_V5_IRQ_CLEAR
#define BWMON_V5_IRQ_ENABLE

#define BWMON_V4_ENABLE
#define BWMON_V5_ENABLE
#define BWMON_ENABLE_ENABLE

#define BWMON_V4_CLEAR
#define BWMON_V5_CLEAR
#define BWMON_CLEAR_CLEAR
#define BWMON_CLEAR_CLEAR_ALL

#define BWMON_V4_SAMPLE_WINDOW
#define BWMON_V5_SAMPLE_WINDOW

#define BWMON_V4_THRESHOLD_HIGH
#define BWMON_V4_THRESHOLD_MED
#define BWMON_V4_THRESHOLD_LOW
#define BWMON_V5_THRESHOLD_HIGH
#define BWMON_V5_THRESHOLD_MED
#define BWMON_V5_THRESHOLD_LOW

#define BWMON_V4_ZONE_ACTIONS
#define BWMON_V5_ZONE_ACTIONS
/*
 * Actions to perform on some zone 'z' when current zone hits the threshold:
 * Increment counter of zone 'z'
 */
#define BWMON_ZONE_ACTIONS_INCREMENT(z)
/* Clear counter of zone 'z' */
#define BWMON_ZONE_ACTIONS_CLEAR(z)

/* Zone 0 threshold hit: Clear zone count */
#define BWMON_ZONE_ACTIONS_ZONE0

/* Zone 1 threshold hit: Increment zone count & clear lower zones */
#define BWMON_ZONE_ACTIONS_ZONE1

/* Zone 2 threshold hit: Increment zone count & clear lower zones */
#define BWMON_ZONE_ACTIONS_ZONE2

/* Zone 3 threshold hit: Increment zone count & clear lower zones */
#define BWMON_ZONE_ACTIONS_ZONE3

/*
 * There is no clear documentation/explanation of BWMON_V4_THRESHOLD_COUNT
 * register. Based on observations, this is number of times one threshold has to
 * be reached, to trigger interrupt in given zone.
 *
 * 0xff are maximum values meant to ignore the zones 0 and 2.
 */
#define BWMON_V4_THRESHOLD_COUNT
#define BWMON_V5_THRESHOLD_COUNT
#define BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT
#define BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT

#define BWMON_V4_ZONE_MAX(zone)
#define BWMON_V5_ZONE_MAX(zone)

/* Quirks for specific BWMON types */
#define BWMON_HAS_GLOBAL_IRQ
#define BWMON_NEEDS_FORCE_CLEAR

enum bwmon_fields {};

struct icc_bwmon_data {};

struct icc_bwmon {};

/* BWMON v4 */
static const struct reg_field msm8998_bwmon_reg_fields[] =;

static const struct regmap_range msm8998_bwmon_reg_noread_ranges[] =;

static const struct regmap_access_table msm8998_bwmon_reg_read_table =;

static const struct regmap_range msm8998_bwmon_reg_volatile_ranges[] =;

static const struct regmap_access_table msm8998_bwmon_reg_volatile_table =;

static const struct reg_field msm8998_bwmon_global_reg_fields[] =;

static const struct regmap_range msm8998_bwmon_global_reg_noread_ranges[] =;

static const struct regmap_access_table msm8998_bwmon_global_reg_read_table =;

/*
 * Fill the cache for non-readable registers only as rest does not really
 * matter and can be read from the device.
 */
static const struct reg_default msm8998_bwmon_reg_defaults[] =;

static const struct reg_default msm8998_bwmon_global_reg_defaults[] =;

static const struct regmap_config msm8998_bwmon_regmap_cfg =;

static const struct regmap_config msm8998_bwmon_global_regmap_cfg =;

static const struct reg_field sdm845_cpu_bwmon_reg_fields[] =;

static const struct regmap_range sdm845_cpu_bwmon_reg_noread_ranges[] =;

static const struct regmap_access_table sdm845_cpu_bwmon_reg_read_table =;

/*
 * Fill the cache for non-readable registers only as rest does not really
 * matter and can be read from the device.
 */
static const struct reg_default sdm845_cpu_bwmon_reg_defaults[] =;

static const struct regmap_config sdm845_cpu_bwmon_regmap_cfg =;

/* BWMON v5 */
static const struct reg_field sdm845_llcc_bwmon_reg_fields[] =;

static const struct regmap_range sdm845_llcc_bwmon_reg_noread_ranges[] =;

static const struct regmap_access_table sdm845_llcc_bwmon_reg_read_table =;

static const struct regmap_range sdm845_llcc_bwmon_reg_volatile_ranges[] =;

static const struct regmap_access_table sdm845_llcc_bwmon_reg_volatile_table =;

/*
 * Fill the cache for non-readable registers only as rest does not really
 * matter and can be read from the device.
 */
static const struct reg_default sdm845_llcc_bwmon_reg_defaults[] =;

static const struct regmap_config sdm845_llcc_bwmon_regmap_cfg =;

static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all)
{}

static void bwmon_clear_irq(struct icc_bwmon *bwmon)
{}

static void bwmon_disable(struct icc_bwmon *bwmon)
{}

static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable)
{}

static unsigned int bwmon_kbps_to_count(struct icc_bwmon *bwmon,
					unsigned int kbps)
{}

static void bwmon_set_threshold(struct icc_bwmon *bwmon,
				struct regmap_field *reg, unsigned int kbps)
{}

static void bwmon_start(struct icc_bwmon *bwmon)
{}

static irqreturn_t bwmon_intr(int irq, void *dev_id)
{}

static irqreturn_t bwmon_intr_thread(int irq, void *dev_id)
{}

static int bwmon_init_regmap(struct platform_device *pdev,
			     struct icc_bwmon *bwmon)
{}

static int bwmon_probe(struct platform_device *pdev)
{}

static void bwmon_remove(struct platform_device *pdev)
{}

static const struct icc_bwmon_data msm8998_bwmon_data =;

static const struct icc_bwmon_data sdm845_cpu_bwmon_data =;

static const struct icc_bwmon_data sdm845_llcc_bwmon_data =;

static const struct icc_bwmon_data sc7280_llcc_bwmon_data =;

static const struct of_device_id bwmon_of_match[] =;
MODULE_DEVICE_TABLE(of, bwmon_of_match);

static struct platform_driver bwmon_driver =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();