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

exynos-bus.c (13059B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Generic Exynos Bus frequency driver with DEVFREQ Framework
      4 *
      5 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
      6 * Author : Chanwoo Choi <cw00.choi@samsung.com>
      7 *
      8 * This driver support Exynos Bus frequency feature by using
      9 * DEVFREQ framework and is based on drivers/devfreq/exynos/exynos4_bus.c.
     10 */
     11
     12#include <linux/clk.h>
     13#include <linux/devfreq.h>
     14#include <linux/devfreq-event.h>
     15#include <linux/device.h>
     16#include <linux/export.h>
     17#include <linux/module.h>
     18#include <linux/of.h>
     19#include <linux/pm_opp.h>
     20#include <linux/platform_device.h>
     21#include <linux/regulator/consumer.h>
     22
     23#define DEFAULT_SATURATION_RATIO	40
     24
     25struct exynos_bus {
     26	struct device *dev;
     27	struct platform_device *icc_pdev;
     28
     29	struct devfreq *devfreq;
     30	struct devfreq_event_dev **edev;
     31	unsigned int edev_count;
     32	struct mutex lock;
     33
     34	unsigned long curr_freq;
     35
     36	struct opp_table *opp_table;
     37	struct clk *clk;
     38	unsigned int ratio;
     39};
     40
     41/*
     42 * Control the devfreq-event device to get the current state of bus
     43 */
     44#define exynos_bus_ops_edev(ops)				\
     45static int exynos_bus_##ops(struct exynos_bus *bus)		\
     46{								\
     47	int i, ret;						\
     48								\
     49	for (i = 0; i < bus->edev_count; i++) {			\
     50		if (!bus->edev[i])				\
     51			continue;				\
     52		ret = devfreq_event_##ops(bus->edev[i]);	\
     53		if (ret < 0)					\
     54			return ret;				\
     55	}							\
     56								\
     57	return 0;						\
     58}
     59exynos_bus_ops_edev(enable_edev);
     60exynos_bus_ops_edev(disable_edev);
     61exynos_bus_ops_edev(set_event);
     62
     63static int exynos_bus_get_event(struct exynos_bus *bus,
     64				struct devfreq_event_data *edata)
     65{
     66	struct devfreq_event_data event_data;
     67	unsigned long load_count = 0, total_count = 0;
     68	int i, ret = 0;
     69
     70	for (i = 0; i < bus->edev_count; i++) {
     71		if (!bus->edev[i])
     72			continue;
     73
     74		ret = devfreq_event_get_event(bus->edev[i], &event_data);
     75		if (ret < 0)
     76			return ret;
     77
     78		if (i == 0 || event_data.load_count > load_count) {
     79			load_count = event_data.load_count;
     80			total_count = event_data.total_count;
     81		}
     82	}
     83
     84	edata->load_count = load_count;
     85	edata->total_count = total_count;
     86
     87	return ret;
     88}
     89
     90/*
     91 * devfreq function for both simple-ondemand and passive governor
     92 */
     93static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
     94{
     95	struct exynos_bus *bus = dev_get_drvdata(dev);
     96	struct dev_pm_opp *new_opp;
     97	int ret = 0;
     98
     99	/* Get correct frequency for bus. */
    100	new_opp = devfreq_recommended_opp(dev, freq, flags);
    101	if (IS_ERR(new_opp)) {
    102		dev_err(dev, "failed to get recommended opp instance\n");
    103		return PTR_ERR(new_opp);
    104	}
    105
    106	dev_pm_opp_put(new_opp);
    107
    108	/* Change voltage and frequency according to new OPP level */
    109	mutex_lock(&bus->lock);
    110	ret = dev_pm_opp_set_rate(dev, *freq);
    111	if (!ret)
    112		bus->curr_freq = *freq;
    113
    114	mutex_unlock(&bus->lock);
    115
    116	return ret;
    117}
    118
    119static int exynos_bus_get_dev_status(struct device *dev,
    120				     struct devfreq_dev_status *stat)
    121{
    122	struct exynos_bus *bus = dev_get_drvdata(dev);
    123	struct devfreq_event_data edata;
    124	int ret;
    125
    126	stat->current_frequency = bus->curr_freq;
    127
    128	ret = exynos_bus_get_event(bus, &edata);
    129	if (ret < 0) {
    130		dev_err(dev, "failed to get event from devfreq-event devices\n");
    131		stat->total_time = stat->busy_time = 0;
    132		goto err;
    133	}
    134
    135	stat->busy_time = (edata.load_count * 100) / bus->ratio;
    136	stat->total_time = edata.total_count;
    137
    138	dev_dbg(dev, "Usage of devfreq-event : %lu/%lu\n", stat->busy_time,
    139							stat->total_time);
    140
    141err:
    142	ret = exynos_bus_set_event(bus);
    143	if (ret < 0) {
    144		dev_err(dev, "failed to set event to devfreq-event devices\n");
    145		return ret;
    146	}
    147
    148	return ret;
    149}
    150
    151static void exynos_bus_exit(struct device *dev)
    152{
    153	struct exynos_bus *bus = dev_get_drvdata(dev);
    154	int ret;
    155
    156	ret = exynos_bus_disable_edev(bus);
    157	if (ret < 0)
    158		dev_warn(dev, "failed to disable the devfreq-event devices\n");
    159
    160	platform_device_unregister(bus->icc_pdev);
    161
    162	dev_pm_opp_of_remove_table(dev);
    163	clk_disable_unprepare(bus->clk);
    164	dev_pm_opp_put_regulators(bus->opp_table);
    165	bus->opp_table = NULL;
    166}
    167
    168static void exynos_bus_passive_exit(struct device *dev)
    169{
    170	struct exynos_bus *bus = dev_get_drvdata(dev);
    171
    172	platform_device_unregister(bus->icc_pdev);
    173
    174	dev_pm_opp_of_remove_table(dev);
    175	clk_disable_unprepare(bus->clk);
    176}
    177
    178static int exynos_bus_parent_parse_of(struct device_node *np,
    179					struct exynos_bus *bus)
    180{
    181	struct device *dev = bus->dev;
    182	struct opp_table *opp_table;
    183	const char *vdd = "vdd";
    184	int i, ret, count, size;
    185
    186	opp_table = dev_pm_opp_set_regulators(dev, &vdd, 1);
    187	if (IS_ERR(opp_table)) {
    188		ret = PTR_ERR(opp_table);
    189		dev_err(dev, "failed to set regulators %d\n", ret);
    190		return ret;
    191	}
    192
    193	bus->opp_table = opp_table;
    194
    195	/*
    196	 * Get the devfreq-event devices to get the current utilization of
    197	 * buses. This raw data will be used in devfreq ondemand governor.
    198	 */
    199	count = devfreq_event_get_edev_count(dev, "devfreq-events");
    200	if (count < 0) {
    201		dev_err(dev, "failed to get the count of devfreq-event dev\n");
    202		ret = count;
    203		goto err_regulator;
    204	}
    205	bus->edev_count = count;
    206
    207	size = sizeof(*bus->edev) * count;
    208	bus->edev = devm_kzalloc(dev, size, GFP_KERNEL);
    209	if (!bus->edev) {
    210		ret = -ENOMEM;
    211		goto err_regulator;
    212	}
    213
    214	for (i = 0; i < count; i++) {
    215		bus->edev[i] = devfreq_event_get_edev_by_phandle(dev,
    216							"devfreq-events", i);
    217		if (IS_ERR(bus->edev[i])) {
    218			ret = -EPROBE_DEFER;
    219			goto err_regulator;
    220		}
    221	}
    222
    223	/*
    224	 * Optionally, Get the saturation ratio according to Exynos SoC
    225	 * When measuring the utilization of each AXI bus with devfreq-event
    226	 * devices, the measured real cycle might be much lower than the
    227	 * total cycle of bus during sampling rate. In result, the devfreq
    228	 * simple-ondemand governor might not decide to change the current
    229	 * frequency due to too utilization (= real cycle/total cycle).
    230	 * So, this property is used to adjust the utilization when calculating
    231	 * the busy_time in exynos_bus_get_dev_status().
    232	 */
    233	if (of_property_read_u32(np, "exynos,saturation-ratio", &bus->ratio))
    234		bus->ratio = DEFAULT_SATURATION_RATIO;
    235
    236	return 0;
    237
    238err_regulator:
    239	dev_pm_opp_put_regulators(bus->opp_table);
    240	bus->opp_table = NULL;
    241
    242	return ret;
    243}
    244
    245static int exynos_bus_parse_of(struct device_node *np,
    246			      struct exynos_bus *bus)
    247{
    248	struct device *dev = bus->dev;
    249	struct dev_pm_opp *opp;
    250	unsigned long rate;
    251	int ret;
    252
    253	/* Get the clock to provide each bus with source clock */
    254	bus->clk = devm_clk_get(dev, "bus");
    255	if (IS_ERR(bus->clk)) {
    256		dev_err(dev, "failed to get bus clock\n");
    257		return PTR_ERR(bus->clk);
    258	}
    259
    260	ret = clk_prepare_enable(bus->clk);
    261	if (ret < 0) {
    262		dev_err(dev, "failed to get enable clock\n");
    263		return ret;
    264	}
    265
    266	/* Get the freq and voltage from OPP table to scale the bus freq */
    267	ret = dev_pm_opp_of_add_table(dev);
    268	if (ret < 0) {
    269		dev_err(dev, "failed to get OPP table\n");
    270		goto err_clk;
    271	}
    272
    273	rate = clk_get_rate(bus->clk);
    274
    275	opp = devfreq_recommended_opp(dev, &rate, 0);
    276	if (IS_ERR(opp)) {
    277		dev_err(dev, "failed to find dev_pm_opp\n");
    278		ret = PTR_ERR(opp);
    279		goto err_opp;
    280	}
    281	bus->curr_freq = dev_pm_opp_get_freq(opp);
    282	dev_pm_opp_put(opp);
    283
    284	return 0;
    285
    286err_opp:
    287	dev_pm_opp_of_remove_table(dev);
    288err_clk:
    289	clk_disable_unprepare(bus->clk);
    290
    291	return ret;
    292}
    293
    294static int exynos_bus_profile_init(struct exynos_bus *bus,
    295				   struct devfreq_dev_profile *profile)
    296{
    297	struct device *dev = bus->dev;
    298	struct devfreq_simple_ondemand_data *ondemand_data;
    299	int ret;
    300
    301	/* Initialize the struct profile and governor data for parent device */
    302	profile->polling_ms = 50;
    303	profile->target = exynos_bus_target;
    304	profile->get_dev_status = exynos_bus_get_dev_status;
    305	profile->exit = exynos_bus_exit;
    306
    307	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
    308	if (!ondemand_data)
    309		return -ENOMEM;
    310
    311	ondemand_data->upthreshold = 40;
    312	ondemand_data->downdifferential = 5;
    313
    314	/* Add devfreq device to monitor and handle the exynos bus */
    315	bus->devfreq = devm_devfreq_add_device(dev, profile,
    316						DEVFREQ_GOV_SIMPLE_ONDEMAND,
    317						ondemand_data);
    318	if (IS_ERR(bus->devfreq)) {
    319		dev_err(dev, "failed to add devfreq device\n");
    320		return PTR_ERR(bus->devfreq);
    321	}
    322
    323	/* Register opp_notifier to catch the change of OPP  */
    324	ret = devm_devfreq_register_opp_notifier(dev, bus->devfreq);
    325	if (ret < 0) {
    326		dev_err(dev, "failed to register opp notifier\n");
    327		return ret;
    328	}
    329
    330	/*
    331	 * Enable devfreq-event to get raw data which is used to determine
    332	 * current bus load.
    333	 */
    334	ret = exynos_bus_enable_edev(bus);
    335	if (ret < 0) {
    336		dev_err(dev, "failed to enable devfreq-event devices\n");
    337		return ret;
    338	}
    339
    340	ret = exynos_bus_set_event(bus);
    341	if (ret < 0) {
    342		dev_err(dev, "failed to set event to devfreq-event devices\n");
    343		goto err_edev;
    344	}
    345
    346	return 0;
    347
    348err_edev:
    349	if (exynos_bus_disable_edev(bus))
    350		dev_warn(dev, "failed to disable the devfreq-event devices\n");
    351
    352	return ret;
    353}
    354
    355static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
    356					   struct devfreq_dev_profile *profile)
    357{
    358	struct device *dev = bus->dev;
    359	struct devfreq_passive_data *passive_data;
    360	struct devfreq *parent_devfreq;
    361
    362	/* Initialize the struct profile and governor data for passive device */
    363	profile->target = exynos_bus_target;
    364	profile->exit = exynos_bus_passive_exit;
    365
    366	/* Get the instance of parent devfreq device */
    367	parent_devfreq = devfreq_get_devfreq_by_phandle(dev, "devfreq", 0);
    368	if (IS_ERR(parent_devfreq))
    369		return -EPROBE_DEFER;
    370
    371	passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
    372	if (!passive_data)
    373		return -ENOMEM;
    374
    375	passive_data->parent = parent_devfreq;
    376
    377	/* Add devfreq device for exynos bus with passive governor */
    378	bus->devfreq = devm_devfreq_add_device(dev, profile, DEVFREQ_GOV_PASSIVE,
    379						passive_data);
    380	if (IS_ERR(bus->devfreq)) {
    381		dev_err(dev,
    382			"failed to add devfreq dev with passive governor\n");
    383		return PTR_ERR(bus->devfreq);
    384	}
    385
    386	return 0;
    387}
    388
    389static int exynos_bus_probe(struct platform_device *pdev)
    390{
    391	struct device *dev = &pdev->dev;
    392	struct device_node *np = dev->of_node, *node;
    393	struct devfreq_dev_profile *profile;
    394	struct exynos_bus *bus;
    395	int ret, max_state;
    396	unsigned long min_freq, max_freq;
    397	bool passive = false;
    398
    399	if (!np) {
    400		dev_err(dev, "failed to find devicetree node\n");
    401		return -EINVAL;
    402	}
    403
    404	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
    405	if (!bus)
    406		return -ENOMEM;
    407	mutex_init(&bus->lock);
    408	bus->dev = &pdev->dev;
    409	platform_set_drvdata(pdev, bus);
    410
    411	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
    412	if (!profile)
    413		return -ENOMEM;
    414
    415	node = of_parse_phandle(dev->of_node, "devfreq", 0);
    416	if (node) {
    417		of_node_put(node);
    418		passive = true;
    419	} else {
    420		ret = exynos_bus_parent_parse_of(np, bus);
    421		if (ret < 0)
    422			return ret;
    423	}
    424
    425	/* Parse the device-tree to get the resource information */
    426	ret = exynos_bus_parse_of(np, bus);
    427	if (ret < 0)
    428		goto err_reg;
    429
    430	if (passive)
    431		ret = exynos_bus_profile_init_passive(bus, profile);
    432	else
    433		ret = exynos_bus_profile_init(bus, profile);
    434
    435	if (ret < 0)
    436		goto err;
    437
    438	/* Create child platform device for the interconnect provider */
    439	if (of_get_property(dev->of_node, "#interconnect-cells", NULL)) {
    440		bus->icc_pdev = platform_device_register_data(
    441						dev, "exynos-generic-icc",
    442						PLATFORM_DEVID_AUTO, NULL, 0);
    443
    444		if (IS_ERR(bus->icc_pdev)) {
    445			ret = PTR_ERR(bus->icc_pdev);
    446			goto err;
    447		}
    448	}
    449
    450	max_state = bus->devfreq->max_state;
    451	min_freq = (bus->devfreq->freq_table[0] / 1000);
    452	max_freq = (bus->devfreq->freq_table[max_state - 1] / 1000);
    453	pr_info("exynos-bus: new bus device registered: %s (%6ld KHz ~ %6ld KHz)\n",
    454			dev_name(dev), min_freq, max_freq);
    455
    456	return 0;
    457
    458err:
    459	dev_pm_opp_of_remove_table(dev);
    460	clk_disable_unprepare(bus->clk);
    461err_reg:
    462	dev_pm_opp_put_regulators(bus->opp_table);
    463	bus->opp_table = NULL;
    464
    465	return ret;
    466}
    467
    468static void exynos_bus_shutdown(struct platform_device *pdev)
    469{
    470	struct exynos_bus *bus = dev_get_drvdata(&pdev->dev);
    471
    472	devfreq_suspend_device(bus->devfreq);
    473}
    474
    475#ifdef CONFIG_PM_SLEEP
    476static int exynos_bus_resume(struct device *dev)
    477{
    478	struct exynos_bus *bus = dev_get_drvdata(dev);
    479	int ret;
    480
    481	ret = exynos_bus_enable_edev(bus);
    482	if (ret < 0) {
    483		dev_err(dev, "failed to enable the devfreq-event devices\n");
    484		return ret;
    485	}
    486
    487	return 0;
    488}
    489
    490static int exynos_bus_suspend(struct device *dev)
    491{
    492	struct exynos_bus *bus = dev_get_drvdata(dev);
    493	int ret;
    494
    495	ret = exynos_bus_disable_edev(bus);
    496	if (ret < 0) {
    497		dev_err(dev, "failed to disable the devfreq-event devices\n");
    498		return ret;
    499	}
    500
    501	return 0;
    502}
    503#endif
    504
    505static const struct dev_pm_ops exynos_bus_pm = {
    506	SET_SYSTEM_SLEEP_PM_OPS(exynos_bus_suspend, exynos_bus_resume)
    507};
    508
    509static const struct of_device_id exynos_bus_of_match[] = {
    510	{ .compatible = "samsung,exynos-bus", },
    511	{ /* sentinel */ },
    512};
    513MODULE_DEVICE_TABLE(of, exynos_bus_of_match);
    514
    515static struct platform_driver exynos_bus_platdrv = {
    516	.probe		= exynos_bus_probe,
    517	.shutdown	= exynos_bus_shutdown,
    518	.driver = {
    519		.name	= "exynos-bus",
    520		.pm	= &exynos_bus_pm,
    521		.of_match_table = of_match_ptr(exynos_bus_of_match),
    522	},
    523};
    524module_platform_driver(exynos_bus_platdrv);
    525
    526MODULE_DESCRIPTION("Generic Exynos Bus frequency driver");
    527MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
    528MODULE_LICENSE("GPL v2");