mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 23:22:31 +02:00
Samsung SoC firmware/clock drivers for v6.19
Extend Samsung ACPM (Alive Clock and Power Manager) firmware drivers:
1. Add support for passing DVFS (Dynamic Voltage and Frequency) messages
to configure the clocks in ACPM device.
2. Add Exynos ACPM clock driver, which exposes to Linux several clocks
handled by the ACPM (firmware).
-----BEGIN PGP SIGNATURE-----
iQJEBAABCgAuFiEE3dJiKD0RGyM7briowTdm5oaLg9cFAmkR1kMQHGtyemtAa2Vy
bmVsLm9yZwAKCRDBN2bmhouD1/8REACWm6l/mfn6ji8q6TziaQ/MmSjCEn0xvGH9
ZmtuBQtFT/KpN2liOckMVX9AUqf3ZjmxaqimbFzO7zBMb/VG/9/8Phofn++jq5dt
h4MQ1XVZRqNlxPP3SA3BMcYj6lEJTK8VvgsM4KqCuZ3yKF/RTlnpOSLRTYzwvIAV
se7DGMp6fBd1Z+igBOfWzjVyv0RyzlDeX7EP6S1AXYcexhuCyfG4oKI0P97A8u2i
B+hKeVrSY2Yuefsi6nJaE7SDjjRLW5kxpE/htzDCzBNzju7KihpbYb4qlzy24L+6
mQ0cjNcysQHmkb45a4QYY6BiX/JlBa+lrHAQ9626afxUZAfJsZG7sdvUBOiu4icp
IIGio1S+rLKEHhModoYvpe9oHNHXpAJr80wZAiGIpryZXjZku21wtb6l3oMO89rz
UkUqhbbqBPOVzI8ucirRFnzOSsKsEcs+NfBGBcvCWyZziKqsuShri3BL15S4fkMW
AnnObhWcssNAgTy0lWma+fOrocu/DyGI6TsNMy/TDu/TgH0FwncK/3e8GFdfwqTP
XUQBN/kTNmJi8GE3iG5bGP1SZRkcHw9VuF5BEjvhtSojcR550nU9Dl5xna3uVLQF
eVI4qbedRzlHj2jGOaB4QDd/1NpBh4ItKELJGD2MDQJXq7VyTeByIStoHxgtX1WU
uyZ59V5UYA==
=4F4S
-----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
iQJIBAABCAAyFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAmkWpCYUHHN3Ym95ZEBj
aHJvbWl1bS5vcmcACgkQrQKIl8bklSUF0xAAzy74TBjuu5ZkLk0ir52rQdyY/D76
fRm49AyvE6DMDWnN5QKK37ospDJn1D7KMqfXA4FWoY9ljEjeQ2nthUPB9zwxYfuQ
P9DxJNeC6/28bhu6vENkfbK28sPwxGPznDvuKvy3msi4V8K/CXTL/qaXZHPCStrA
Bye/i0/h+u3vonQI+ti6D3F7ZV4Tic80OReDLAMyg3RteLEYRAJDmh1QFWjW8LVb
rGhA2GBnnM3wo/zZEL3phXtHuVy3WS1vjY8v15p7G5etNNLHA2V1C5c8Kl+svwrV
DD+HmWRmMqlZUS5uUL1sYEOJcxVau1KFQyOUCqpMz5meTJ6EqAfar7z2v0DvDGhQ
f6Kj6XbesMA0Iy5Bm8ulLeQRoj91rteM+Z9bILZnKSl9PN4dvZ4qqPASGux7+sgQ
dRGpenaijVE/W9PHaOf0fq5B/04gyg4eUDmIWCWnvdqlrwtj7StBFLLGjkwXBCcy
gw+q+Ws0ddyMF93GqTbQDlCi7QvLAAjDseDu0ApExX3nRMwPz9y/ZRhro6Yfbo0s
6w+kyYyaaalThodhC4j4N7m0XAiEhCtBMiZc6QQ4/dlalX6VdRNKXa6gW5jjnHLd
5tkLopxPeNTBz2NW+cstWIcY+TcHOwt+QUu+EtTzcW84SPWSRc/5Y9+exKyGAYOQ
GitnlNSG24+cvsw=
=susi
-----END PGP SIGNATURE-----
Merge tag 'samsung-drivers-firmware-clk-6.19' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into clk-samsung
Pull Samsung clk driver updates from Krzysztof Kozlowski:
Extend Samsung ACPM (Alive Clock and Power Manager) firmware drivers:
- Add support for passing DVFS (Dynamic Voltage and Frequency) messages
to configure the clocks in ACPM device.
- Add Exynos ACPM clock driver, which exposes to Linux several clocks
handled by the ACPM (firmware)
* tag 'samsung-drivers-firmware-clk-6.19' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux:
firmware: exynos-acpm: add empty method to allow compile test
MAINTAINERS: add ACPM clock bindings and driver
clk: samsung: add Exynos ACPM clock driver
firmware: exynos-acpm: register ACPM clocks pdev
firmware: exynos-acpm: add DVFS protocol
dt-bindings: firmware: google,gs101-acpm-ipc: add ACPM clocks
This commit is contained in:
commit
44244194e1
|
|
@ -24,6 +24,15 @@ properties:
|
|||
compatible:
|
||||
const: google,gs101-acpm-ipc
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
description:
|
||||
Clocks that are variable and index based. These clocks don't provide
|
||||
an entire range of values between the limits but only discrete points
|
||||
within the range. The firmware also manages the voltage scaling
|
||||
appropriately with the clock scaling. The argument is the ID of the
|
||||
clock contained by the firmware messages.
|
||||
|
||||
mboxes:
|
||||
maxItems: 1
|
||||
|
||||
|
|
@ -45,6 +54,7 @@ properties:
|
|||
|
||||
required:
|
||||
- compatible
|
||||
- "#clock-cells"
|
||||
- mboxes
|
||||
- shmem
|
||||
|
||||
|
|
@ -56,6 +66,7 @@ examples:
|
|||
|
||||
power-management {
|
||||
compatible = "google,gs101-acpm-ipc";
|
||||
#clock-cells = <1>;
|
||||
mboxes = <&ap2apm_mailbox>;
|
||||
shmem = <&apm_sram>;
|
||||
|
||||
|
|
|
|||
|
|
@ -10601,7 +10601,7 @@ F: Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml
|
|||
F: arch/arm64/boot/dts/exynos/google/
|
||||
F: drivers/clk/samsung/clk-gs101.c
|
||||
F: drivers/phy/samsung/phy-gs101-ufs.c
|
||||
F: include/dt-bindings/clock/google,gs101.h
|
||||
F: include/dt-bindings/clock/google,gs101*
|
||||
K: [gG]oogle.?[tT]ensor
|
||||
|
||||
GPD FAN DRIVER
|
||||
|
|
@ -22761,6 +22761,7 @@ L: linux-kernel@vger.kernel.org
|
|||
L: linux-samsung-soc@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
|
||||
F: drivers/clk/samsung/clk-acpm.c
|
||||
F: drivers/firmware/samsung/exynos-acpm*
|
||||
F: include/linux/firmware/samsung/exynos-acpm-protocol.h
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,16 @@ config EXYNOS_CLKOUT
|
|||
status of the certains clocks from SoC, but it could also be tied to
|
||||
other devices as an input clock.
|
||||
|
||||
config EXYNOS_ACPM_CLK
|
||||
tristate "Clock driver controlled via ACPM interface"
|
||||
depends on EXYNOS_ACPM_PROTOCOL || (COMPILE_TEST && !EXYNOS_ACPM_PROTOCOL)
|
||||
help
|
||||
This driver provides support for clocks that are controlled by
|
||||
firmware that implements the ACPM interface.
|
||||
|
||||
This driver uses the ACPM interface to interact with the firmware
|
||||
providing all the clock controlls.
|
||||
|
||||
config TESLA_FSD_COMMON_CLK
|
||||
bool "Tesla FSD clock controller support" if COMPILE_TEST
|
||||
depends on COMMON_CLK_SAMSUNG
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos990.o
|
|||
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynosautov9.o
|
||||
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynosautov920.o
|
||||
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-gs101.o
|
||||
obj-$(CONFIG_EXYNOS_ACPM_CLK) += clk-acpm.o
|
||||
obj-$(CONFIG_S3C64XX_COMMON_CLK) += clk-s3c64xx.o
|
||||
obj-$(CONFIG_S5PV210_COMMON_CLK) += clk-s5pv210.o clk-s5pv210-audss.o
|
||||
obj-$(CONFIG_TESLA_FSD_COMMON_CLK) += clk-fsd.o
|
||||
|
|
|
|||
185
drivers/clk/samsung/clk-acpm.c
Normal file
185
drivers/clk/samsung/clk-acpm.c
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Samsung Exynos ACPM protocol based clock driver.
|
||||
*
|
||||
* Copyright 2025 Linaro Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/container_of.h>
|
||||
#include <linux/device/devres.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct acpm_clk {
|
||||
u32 id;
|
||||
struct clk_hw hw;
|
||||
unsigned int mbox_chan_id;
|
||||
const struct acpm_handle *handle;
|
||||
};
|
||||
|
||||
struct acpm_clk_variant {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct acpm_clk_driver_data {
|
||||
const struct acpm_clk_variant *clks;
|
||||
unsigned int nr_clks;
|
||||
unsigned int mbox_chan_id;
|
||||
};
|
||||
|
||||
#define to_acpm_clk(clk) container_of(clk, struct acpm_clk, hw)
|
||||
|
||||
#define ACPM_CLK(cname) \
|
||||
{ \
|
||||
.name = cname, \
|
||||
}
|
||||
|
||||
static const struct acpm_clk_variant gs101_acpm_clks[] = {
|
||||
ACPM_CLK("mif"),
|
||||
ACPM_CLK("int"),
|
||||
ACPM_CLK("cpucl0"),
|
||||
ACPM_CLK("cpucl1"),
|
||||
ACPM_CLK("cpucl2"),
|
||||
ACPM_CLK("g3d"),
|
||||
ACPM_CLK("g3dl2"),
|
||||
ACPM_CLK("tpu"),
|
||||
ACPM_CLK("intcam"),
|
||||
ACPM_CLK("tnr"),
|
||||
ACPM_CLK("cam"),
|
||||
ACPM_CLK("mfc"),
|
||||
ACPM_CLK("disp"),
|
||||
ACPM_CLK("bo"),
|
||||
};
|
||||
|
||||
static const struct acpm_clk_driver_data acpm_clk_gs101 = {
|
||||
.clks = gs101_acpm_clks,
|
||||
.nr_clks = ARRAY_SIZE(gs101_acpm_clks),
|
||||
.mbox_chan_id = 0,
|
||||
};
|
||||
|
||||
static unsigned long acpm_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct acpm_clk *clk = to_acpm_clk(hw);
|
||||
|
||||
return clk->handle->ops.dvfs_ops.get_rate(clk->handle,
|
||||
clk->mbox_chan_id, clk->id);
|
||||
}
|
||||
|
||||
static int acpm_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
/*
|
||||
* We can't figure out what rate it will be, so just return the
|
||||
* rate back to the caller. acpm_clk_recalc_rate() will be called
|
||||
* after the rate is set and we'll know what rate the clock is
|
||||
* running at then.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct acpm_clk *clk = to_acpm_clk(hw);
|
||||
|
||||
return clk->handle->ops.dvfs_ops.set_rate(clk->handle,
|
||||
clk->mbox_chan_id, clk->id, rate);
|
||||
}
|
||||
|
||||
static const struct clk_ops acpm_clk_ops = {
|
||||
.recalc_rate = acpm_clk_recalc_rate,
|
||||
.determine_rate = acpm_clk_determine_rate,
|
||||
.set_rate = acpm_clk_set_rate,
|
||||
};
|
||||
|
||||
static int acpm_clk_register(struct device *dev, struct acpm_clk *aclk,
|
||||
const char *name)
|
||||
{
|
||||
struct clk_init_data init = {};
|
||||
|
||||
init.name = name;
|
||||
init.ops = &acpm_clk_ops;
|
||||
aclk->hw.init = &init;
|
||||
|
||||
return devm_clk_hw_register(dev, &aclk->hw);
|
||||
}
|
||||
|
||||
static int acpm_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct acpm_handle *acpm_handle;
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
struct clk_hw **hws;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct acpm_clk *aclks;
|
||||
unsigned int mbox_chan_id;
|
||||
int i, err, count;
|
||||
|
||||
acpm_handle = devm_acpm_get_by_node(dev, dev->parent->of_node);
|
||||
if (IS_ERR(acpm_handle))
|
||||
return dev_err_probe(dev, PTR_ERR(acpm_handle),
|
||||
"Failed to get acpm handle\n");
|
||||
|
||||
count = acpm_clk_gs101.nr_clks;
|
||||
mbox_chan_id = acpm_clk_gs101.mbox_chan_id;
|
||||
|
||||
clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count),
|
||||
GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
clk_data->num = count;
|
||||
hws = clk_data->hws;
|
||||
|
||||
aclks = devm_kcalloc(dev, count, sizeof(*aclks), GFP_KERNEL);
|
||||
if (!aclks)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct acpm_clk *aclk = &aclks[i];
|
||||
|
||||
/*
|
||||
* The code assumes the clock IDs start from zero,
|
||||
* are sequential and do not have gaps.
|
||||
*/
|
||||
aclk->id = i;
|
||||
aclk->handle = acpm_handle;
|
||||
aclk->mbox_chan_id = mbox_chan_id;
|
||||
|
||||
hws[i] = &aclk->hw;
|
||||
|
||||
err = acpm_clk_register(dev, aclk,
|
||||
acpm_clk_gs101.clks[i].name);
|
||||
if (err)
|
||||
return dev_err_probe(dev, err,
|
||||
"Failed to register clock\n");
|
||||
}
|
||||
|
||||
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
|
||||
clk_data);
|
||||
}
|
||||
|
||||
static const struct platform_device_id acpm_clk_id[] = {
|
||||
{ "gs101-acpm-clk" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, acpm_clk_id);
|
||||
|
||||
static struct platform_driver acpm_clk_driver = {
|
||||
.driver = {
|
||||
.name = "acpm-clocks",
|
||||
},
|
||||
.probe = acpm_clk_probe,
|
||||
.id_table = acpm_clk_id,
|
||||
};
|
||||
module_platform_driver(acpm_clk_driver);
|
||||
|
||||
MODULE_AUTHOR("Tudor Ambarus <tudor.ambarus@linaro.org>");
|
||||
MODULE_DESCRIPTION("Samsung Exynos ACPM clock driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
acpm-protocol-objs := exynos-acpm.o exynos-acpm-pmic.o
|
||||
acpm-protocol-objs := exynos-acpm.o
|
||||
acpm-protocol-objs += exynos-acpm-pmic.o
|
||||
acpm-protocol-objs += exynos-acpm-dvfs.o
|
||||
obj-$(CONFIG_EXYNOS_ACPM_PROTOCOL) += acpm-protocol.o
|
||||
|
|
|
|||
80
drivers/firmware/samsung/exynos-acpm-dvfs.c
Normal file
80
drivers/firmware/samsung/exynos-acpm-dvfs.c
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright 2020 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2020 Google LLC.
|
||||
* Copyright 2025 Linaro Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include "exynos-acpm.h"
|
||||
#include "exynos-acpm-dvfs.h"
|
||||
|
||||
#define ACPM_DVFS_ID GENMASK(11, 0)
|
||||
#define ACPM_DVFS_REQ_TYPE GENMASK(15, 0)
|
||||
|
||||
#define ACPM_DVFS_FREQ_REQ 0
|
||||
#define ACPM_DVFS_FREQ_GET 1
|
||||
|
||||
static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
|
||||
unsigned int acpm_chan_id, bool response)
|
||||
{
|
||||
xfer->acpm_chan_id = acpm_chan_id;
|
||||
xfer->txd = cmd;
|
||||
xfer->txlen = cmdlen;
|
||||
|
||||
if (response) {
|
||||
xfer->rxd = cmd;
|
||||
xfer->rxlen = cmdlen;
|
||||
}
|
||||
}
|
||||
|
||||
static void acpm_dvfs_init_set_rate_cmd(u32 cmd[4], unsigned int clk_id,
|
||||
unsigned long rate)
|
||||
{
|
||||
cmd[0] = FIELD_PREP(ACPM_DVFS_ID, clk_id);
|
||||
cmd[1] = rate / HZ_PER_KHZ;
|
||||
cmd[2] = FIELD_PREP(ACPM_DVFS_REQ_TYPE, ACPM_DVFS_FREQ_REQ);
|
||||
cmd[3] = ktime_to_ms(ktime_get());
|
||||
}
|
||||
|
||||
int acpm_dvfs_set_rate(const struct acpm_handle *handle,
|
||||
unsigned int acpm_chan_id, unsigned int clk_id,
|
||||
unsigned long rate)
|
||||
{
|
||||
struct acpm_xfer xfer = {0};
|
||||
u32 cmd[4];
|
||||
|
||||
acpm_dvfs_init_set_rate_cmd(cmd, clk_id, rate);
|
||||
acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, false);
|
||||
|
||||
return acpm_do_xfer(handle, &xfer);
|
||||
}
|
||||
|
||||
static void acpm_dvfs_init_get_rate_cmd(u32 cmd[4], unsigned int clk_id)
|
||||
{
|
||||
cmd[0] = FIELD_PREP(ACPM_DVFS_ID, clk_id);
|
||||
cmd[2] = FIELD_PREP(ACPM_DVFS_REQ_TYPE, ACPM_DVFS_FREQ_GET);
|
||||
cmd[3] = ktime_to_ms(ktime_get());
|
||||
}
|
||||
|
||||
unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
|
||||
unsigned int acpm_chan_id, unsigned int clk_id)
|
||||
{
|
||||
struct acpm_xfer xfer;
|
||||
unsigned int cmd[4] = {0};
|
||||
int ret;
|
||||
|
||||
acpm_dvfs_init_get_rate_cmd(cmd, clk_id);
|
||||
acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, true);
|
||||
|
||||
ret = acpm_do_xfer(handle, &xfer);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
return xfer.rxd[1] * HZ_PER_KHZ;
|
||||
}
|
||||
21
drivers/firmware/samsung/exynos-acpm-dvfs.h
Normal file
21
drivers/firmware/samsung/exynos-acpm-dvfs.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright 2020 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2020 Google LLC.
|
||||
* Copyright 2025 Linaro Ltd.
|
||||
*/
|
||||
#ifndef __EXYNOS_ACPM_DVFS_H__
|
||||
#define __EXYNOS_ACPM_DVFS_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct acpm_handle;
|
||||
|
||||
int acpm_dvfs_set_rate(const struct acpm_handle *handle,
|
||||
unsigned int acpm_chan_id, unsigned int id,
|
||||
unsigned long rate);
|
||||
unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
|
||||
unsigned int acpm_chan_id,
|
||||
unsigned int clk_id);
|
||||
|
||||
#endif /* __EXYNOS_ACPM_DVFS_H__ */
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
#include "exynos-acpm.h"
|
||||
#include "exynos-acpm-dvfs.h"
|
||||
#include "exynos-acpm-pmic.h"
|
||||
|
||||
#define ACPM_PROTOCOL_SEQNUM GENMASK(21, 16)
|
||||
|
|
@ -176,9 +177,11 @@ struct acpm_info {
|
|||
/**
|
||||
* struct acpm_match_data - of_device_id data.
|
||||
* @initdata_base: offset in SRAM where the channels configuration resides.
|
||||
* @acpm_clk_dev_name: base name for the ACPM clocks device that we're registering.
|
||||
*/
|
||||
struct acpm_match_data {
|
||||
loff_t initdata_base;
|
||||
const char *acpm_clk_dev_name;
|
||||
};
|
||||
|
||||
#define client_to_acpm_chan(c) container_of(c, struct acpm_chan, cl)
|
||||
|
|
@ -590,8 +593,12 @@ static int acpm_channels_init(struct acpm_info *acpm)
|
|||
*/
|
||||
static void acpm_setup_ops(struct acpm_info *acpm)
|
||||
{
|
||||
struct acpm_dvfs_ops *dvfs_ops = &acpm->handle.ops.dvfs_ops;
|
||||
struct acpm_pmic_ops *pmic_ops = &acpm->handle.ops.pmic_ops;
|
||||
|
||||
dvfs_ops->set_rate = acpm_dvfs_set_rate;
|
||||
dvfs_ops->get_rate = acpm_dvfs_get_rate;
|
||||
|
||||
pmic_ops->read_reg = acpm_pmic_read_reg;
|
||||
pmic_ops->bulk_read = acpm_pmic_bulk_read;
|
||||
pmic_ops->write_reg = acpm_pmic_write_reg;
|
||||
|
|
@ -599,9 +606,15 @@ static void acpm_setup_ops(struct acpm_info *acpm)
|
|||
pmic_ops->update_reg = acpm_pmic_update_reg;
|
||||
}
|
||||
|
||||
static void acpm_clk_pdev_unregister(void *data)
|
||||
{
|
||||
platform_device_unregister(data);
|
||||
}
|
||||
|
||||
static int acpm_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct acpm_match_data *match_data;
|
||||
struct platform_device *acpm_clk_pdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *shmem;
|
||||
struct acpm_info *acpm;
|
||||
|
|
@ -642,6 +655,18 @@ static int acpm_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, acpm);
|
||||
|
||||
acpm_clk_pdev = platform_device_register_data(dev,
|
||||
match_data->acpm_clk_dev_name,
|
||||
PLATFORM_DEVID_NONE, NULL, 0);
|
||||
if (IS_ERR(acpm_clk_pdev))
|
||||
return dev_err_probe(dev, PTR_ERR(acpm_clk_pdev),
|
||||
"Failed to register ACPM clocks device.\n");
|
||||
|
||||
ret = devm_add_action_or_reset(dev, acpm_clk_pdev_unregister,
|
||||
acpm_clk_pdev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to add devm action.\n");
|
||||
|
||||
return devm_of_platform_populate(dev);
|
||||
}
|
||||
|
||||
|
|
@ -741,6 +766,7 @@ EXPORT_SYMBOL_GPL(devm_acpm_get_by_node);
|
|||
|
||||
static const struct acpm_match_data acpm_gs101 = {
|
||||
.initdata_base = ACPM_GS101_INITDATA_BASE,
|
||||
.acpm_clk_dev_name = "gs101-acpm-clk",
|
||||
};
|
||||
|
||||
static const struct of_device_id acpm_match[] = {
|
||||
|
|
|
|||
26
include/dt-bindings/clock/google,gs101-acpm.h
Normal file
26
include/dt-bindings/clock/google,gs101-acpm.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||
/*
|
||||
* Copyright 2025 Linaro Ltd.
|
||||
*
|
||||
* Device Tree binding constants for Google gs101 ACPM clock controller.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_CLOCK_GOOGLE_GS101_ACPM_H
|
||||
#define _DT_BINDINGS_CLOCK_GOOGLE_GS101_ACPM_H
|
||||
|
||||
#define GS101_CLK_ACPM_DVFS_MIF 0
|
||||
#define GS101_CLK_ACPM_DVFS_INT 1
|
||||
#define GS101_CLK_ACPM_DVFS_CPUCL0 2
|
||||
#define GS101_CLK_ACPM_DVFS_CPUCL1 3
|
||||
#define GS101_CLK_ACPM_DVFS_CPUCL2 4
|
||||
#define GS101_CLK_ACPM_DVFS_G3D 5
|
||||
#define GS101_CLK_ACPM_DVFS_G3DL2 6
|
||||
#define GS101_CLK_ACPM_DVFS_TPU 7
|
||||
#define GS101_CLK_ACPM_DVFS_INTCAM 8
|
||||
#define GS101_CLK_ACPM_DVFS_TNR 9
|
||||
#define GS101_CLK_ACPM_DVFS_CAM 10
|
||||
#define GS101_CLK_ACPM_DVFS_MFC 11
|
||||
#define GS101_CLK_ACPM_DVFS_DISP 12
|
||||
#define GS101_CLK_ACPM_DVFS_BO 13
|
||||
|
||||
#endif /* _DT_BINDINGS_CLOCK_GOOGLE_GS101_ACPM_H */
|
||||
|
|
@ -13,6 +13,15 @@
|
|||
struct acpm_handle;
|
||||
struct device_node;
|
||||
|
||||
struct acpm_dvfs_ops {
|
||||
int (*set_rate)(const struct acpm_handle *handle,
|
||||
unsigned int acpm_chan_id, unsigned int clk_id,
|
||||
unsigned long rate);
|
||||
unsigned long (*get_rate)(const struct acpm_handle *handle,
|
||||
unsigned int acpm_chan_id,
|
||||
unsigned int clk_id);
|
||||
};
|
||||
|
||||
struct acpm_pmic_ops {
|
||||
int (*read_reg)(const struct acpm_handle *handle,
|
||||
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
|
||||
|
|
@ -32,6 +41,7 @@ struct acpm_pmic_ops {
|
|||
};
|
||||
|
||||
struct acpm_ops {
|
||||
struct acpm_dvfs_ops dvfs_ops;
|
||||
struct acpm_pmic_ops pmic_ops;
|
||||
};
|
||||
|
||||
|
|
@ -45,7 +55,16 @@ struct acpm_handle {
|
|||
|
||||
struct device;
|
||||
|
||||
#if IS_ENABLED(CONFIG_EXYNOS_ACPM_PROTOCOL)
|
||||
const struct acpm_handle *devm_acpm_get_by_node(struct device *dev,
|
||||
struct device_node *np);
|
||||
#else
|
||||
|
||||
static inline const struct acpm_handle *devm_acpm_get_by_node(struct device *dev,
|
||||
struct device_node *np)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __EXYNOS_ACPM_PROTOCOL_H */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user