Skip to content

Commit e4543de

Browse files
bingbucaojwrdegoede
authored andcommitted
platform/x86: int3472: Evaluate device's _DSM method to control imaging clock
On some platforms, the imaging clock should be controlled by evaluating specific clock device's _DSM method instead of setting gpio, so this change register clock if no gpio based clock and then use the _DSM method to enable and disable clock. Signed-off-by: Bingbu Cao <[email protected]> Signed-off-by: Hao Yao <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 139332e commit e4543de

File tree

3 files changed

+99
-15
lines changed

3 files changed

+99
-15
lines changed

drivers/platform/x86/intel/int3472/clk_and_regulator.c

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,41 @@
1111

1212
#include "common.h"
1313

14+
/*
15+
* 82c0d13a-78c5-4244-9bb1-eb8b539a8d11
16+
* This _DSM GUID allows controlling the sensor clk when it is not controlled
17+
* through a GPIO.
18+
*/
19+
static const guid_t img_clk_guid =
20+
GUID_INIT(0x82c0d13a, 0x78c5, 0x4244,
21+
0x9b, 0xb1, 0xeb, 0x8b, 0x53, 0x9a, 0x8d, 0x11);
22+
23+
static void skl_int3472_enable_clk(struct int3472_clock *clk, int enable)
24+
{
25+
struct int3472_discrete_device *int3472 = to_int3472_device(clk);
26+
union acpi_object args[3];
27+
union acpi_object argv4;
28+
29+
if (clk->ena_gpio) {
30+
gpiod_set_value_cansleep(clk->ena_gpio, enable);
31+
return;
32+
}
33+
34+
args[0].integer.type = ACPI_TYPE_INTEGER;
35+
args[0].integer.value = clk->imgclk_index;
36+
args[1].integer.type = ACPI_TYPE_INTEGER;
37+
args[1].integer.value = enable;
38+
args[2].integer.type = ACPI_TYPE_INTEGER;
39+
args[2].integer.value = 1;
40+
41+
argv4.type = ACPI_TYPE_PACKAGE;
42+
argv4.package.count = 3;
43+
argv4.package.elements = args;
44+
45+
acpi_evaluate_dsm(acpi_device_handle(int3472->adev), &img_clk_guid,
46+
0, 1, &argv4);
47+
}
48+
1449
/*
1550
* The regulators have to have .ops to be valid, but the only ops we actually
1651
* support are .enable and .disable which are handled via .ena_gpiod. Pass an
@@ -20,17 +55,13 @@ static const struct regulator_ops int3472_gpio_regulator_ops;
2055

2156
static int skl_int3472_clk_prepare(struct clk_hw *hw)
2257
{
23-
struct int3472_gpio_clock *clk = to_int3472_clk(hw);
24-
25-
gpiod_set_value_cansleep(clk->ena_gpio, 1);
58+
skl_int3472_enable_clk(to_int3472_clk(hw), 1);
2659
return 0;
2760
}
2861

2962
static void skl_int3472_clk_unprepare(struct clk_hw *hw)
3063
{
31-
struct int3472_gpio_clock *clk = to_int3472_clk(hw);
32-
33-
gpiod_set_value_cansleep(clk->ena_gpio, 0);
64+
skl_int3472_enable_clk(to_int3472_clk(hw), 0);
3465
}
3566

3667
static int skl_int3472_clk_enable(struct clk_hw *hw)
@@ -73,7 +104,7 @@ static unsigned int skl_int3472_get_clk_frequency(struct int3472_discrete_device
73104
static unsigned long skl_int3472_clk_recalc_rate(struct clk_hw *hw,
74105
unsigned long parent_rate)
75106
{
76-
struct int3472_gpio_clock *clk = to_int3472_clk(hw);
107+
struct int3472_clock *clk = to_int3472_clk(hw);
77108

78109
return clk->frequency;
79110
}
@@ -86,8 +117,51 @@ static const struct clk_ops skl_int3472_clock_ops = {
86117
.recalc_rate = skl_int3472_clk_recalc_rate,
87118
};
88119

89-
int skl_int3472_register_clock(struct int3472_discrete_device *int3472,
90-
struct acpi_resource_gpio *agpio, u32 polarity)
120+
int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472)
121+
{
122+
struct acpi_device *adev = int3472->adev;
123+
struct clk_init_data init = {
124+
.ops = &skl_int3472_clock_ops,
125+
.flags = CLK_GET_RATE_NOCACHE,
126+
};
127+
int ret;
128+
129+
if (int3472->clock.cl)
130+
return 0; /* A GPIO controlled clk has already been registered */
131+
132+
if (!acpi_check_dsm(adev->handle, &img_clk_guid, 0, BIT(1)))
133+
return 0; /* DSM clock control is not available */
134+
135+
init.name = kasprintf(GFP_KERNEL, "%s-clk", acpi_dev_name(adev));
136+
if (!init.name)
137+
return -ENOMEM;
138+
139+
int3472->clock.frequency = skl_int3472_get_clk_frequency(int3472);
140+
int3472->clock.clk_hw.init = &init;
141+
int3472->clock.clk = clk_register(&adev->dev, &int3472->clock.clk_hw);
142+
if (IS_ERR(int3472->clock.clk)) {
143+
ret = PTR_ERR(int3472->clock.clk);
144+
goto out_free_init_name;
145+
}
146+
147+
int3472->clock.cl = clkdev_create(int3472->clock.clk, NULL, int3472->sensor_name);
148+
if (!int3472->clock.cl) {
149+
ret = -ENOMEM;
150+
goto err_unregister_clk;
151+
}
152+
153+
kfree(init.name);
154+
return 0;
155+
156+
err_unregister_clk:
157+
clk_unregister(int3472->clock.clk);
158+
out_free_init_name:
159+
kfree(init.name);
160+
return ret;
161+
}
162+
163+
int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472,
164+
struct acpi_resource_gpio *agpio, u32 polarity)
91165
{
92166
char *path = agpio->resource_source.string_ptr;
93167
struct clk_init_data init = {

drivers/platform/x86/intel/int3472/common.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
}
4444

4545
#define to_int3472_clk(hw) \
46-
container_of(hw, struct int3472_gpio_clock, clk_hw)
46+
container_of(hw, struct int3472_clock, clk_hw)
4747

4848
#define to_int3472_device(clk) \
4949
container_of(clk, struct int3472_discrete_device, clock)
@@ -64,7 +64,9 @@ struct int3472_cldb {
6464
u8 control_logic_type;
6565
u8 control_logic_id;
6666
u8 sensor_card_sku;
67-
u8 reserved[28];
67+
u8 reserved[10];
68+
u8 clock_source;
69+
u8 reserved2[17];
6870
};
6971

7072
struct int3472_gpio_function_remap {
@@ -94,12 +96,13 @@ struct int3472_discrete_device {
9496
struct regulator_desc rdesc;
9597
} regulator;
9698

97-
struct int3472_gpio_clock {
99+
struct int3472_clock {
98100
struct clk *clk;
99101
struct clk_hw clk_hw;
100102
struct clk_lookup *cl;
101103
struct gpio_desc *ena_gpio;
102104
u32 frequency;
105+
u8 imgclk_index;
103106
} clock;
104107

105108
struct int3472_pled {
@@ -121,8 +124,9 @@ int skl_int3472_get_sensor_adev_and_name(struct device *dev,
121124
struct acpi_device **sensor_adev_ret,
122125
const char **name_ret);
123126

124-
int skl_int3472_register_clock(struct int3472_discrete_device *int3472,
125-
struct acpi_resource_gpio *agpio, u32 polarity);
127+
int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472,
128+
struct acpi_resource_gpio *agpio, u32 polarity);
129+
int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472);
126130
void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472);
127131

128132
int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,

drivers/platform/x86/intel/int3472/discrete.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
258258

259259
break;
260260
case INT3472_GPIO_TYPE_CLK_ENABLE:
261-
ret = skl_int3472_register_clock(int3472, agpio, polarity);
261+
ret = skl_int3472_register_gpio_clock(int3472, agpio, polarity);
262262
if (ret)
263263
err_msg = "Failed to register clock\n";
264264

@@ -311,6 +311,11 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472)
311311

312312
acpi_dev_free_resource_list(&resource_list);
313313

314+
/* Register _DSM based clock (no-op if a GPIO clock was already registered) */
315+
ret = skl_int3472_register_dsm_clock(int3472);
316+
if (ret < 0)
317+
return ret;
318+
314319
int3472->gpios.dev_id = int3472->sensor_name;
315320
gpiod_add_lookup_table(&int3472->gpios);
316321

@@ -356,6 +361,7 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev)
356361
int3472->adev = adev;
357362
int3472->dev = &pdev->dev;
358363
platform_set_drvdata(pdev, int3472);
364+
int3472->clock.imgclk_index = cldb.clock_source;
359365

360366
ret = skl_int3472_get_sensor_adev_and_name(&pdev->dev, &int3472->sensor,
361367
&int3472->sensor_name);

0 commit comments

Comments
 (0)