summaryrefslogtreecommitdiff
path: root/include/linux/platform_data/x86/int3472.h
blob: 78276a11c48d6c0de0bfaf165c40042d314e58c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Intel INT3472 ACPI camera sensor power-management support
 *
 * Author: Dan Scally <djrscally@gmail.com>
 */

#ifndef __PLATFORM_DATA_X86_INT3472_H
#define __PLATFORM_DATA_X86_INT3472_H

#include <linux/clk-provider.h>
#include <linux/gpio/machine.h>
#include <linux/leds.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/types.h>

/* FIXME drop this once the I2C_DEV_NAME_FORMAT macro has been added to include/linux/i2c.h */
#ifndef I2C_DEV_NAME_FORMAT
#define I2C_DEV_NAME_FORMAT					"i2c-%s"
#endif

/* PMIC GPIO Types */
#define INT3472_GPIO_TYPE_RESET					0x00
#define INT3472_GPIO_TYPE_POWERDOWN				0x01
#define INT3472_GPIO_TYPE_POWER_ENABLE				0x0b
#define INT3472_GPIO_TYPE_CLK_ENABLE				0x0c
#define INT3472_GPIO_TYPE_PRIVACY_LED				0x0d
#define INT3472_GPIO_TYPE_HANDSHAKE				0x12

#define INT3472_PDEV_MAX_NAME_LEN				23
#define INT3472_MAX_SENSOR_GPIOS				3
#define INT3472_MAX_REGULATORS					3

/* E.g. "avdd\0" */
#define GPIO_SUPPLY_NAME_LENGTH				5
/* 12 chars for acpi_dev_name() + "-", e.g. "ABCD1234:00-" */
#define GPIO_REGULATOR_NAME_LENGTH				(12 + GPIO_SUPPLY_NAME_LENGTH)
/* lower- and upper-case mapping */
#define GPIO_REGULATOR_SUPPLY_MAP_COUNT				2
/*
 * Ensure the GPIO is driven low/high for at least 2 ms before changing.
 *
 * 2 ms has been chosen because it is the minimum time ovXXXX sensors need to
 * have their reset line driven logical high to properly register a reset.
 */
#define GPIO_REGULATOR_ENABLE_TIME				(2 * USEC_PER_MSEC)
#define GPIO_REGULATOR_OFF_ON_DELAY				(2 * USEC_PER_MSEC)

#define INT3472_LED_MAX_NAME_LEN				32

#define CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET			86

#define INT3472_REGULATOR(_name, _ops, _enable_time, _off_on_delay) \
	(const struct regulator_desc) {				\
		.name = _name,					\
		.type = REGULATOR_VOLTAGE,			\
		.ops = _ops,					\
		.owner = THIS_MODULE,				\
		.enable_time = _enable_time,			\
		.off_on_delay = _off_on_delay,			\
	}

#define to_int3472_clk(hw)					\
	container_of(hw, struct int3472_clock, clk_hw)

#define to_int3472_device(clk)					\
	container_of(clk, struct int3472_discrete_device, clock)

struct acpi_device;
struct dmi_system_id;
struct i2c_client;
struct platform_device;

struct int3472_cldb {
	u8 version;
	/*
	 * control logic type
	 * 0: UNKNOWN
	 * 1: DISCRETE(CRD-D)
	 * 2: PMIC TPS68470
	 * 3: PMIC uP6641
	 */
	u8 control_logic_type;
	u8 control_logic_id;
	u8 sensor_card_sku;
	u8 reserved[10];
	u8 clock_source;
	u8 reserved2[17];
};

struct int3472_discrete_quirks {
	/* For models where AVDD GPIO is shared between sensors */
	const char *avdd_second_sensor;
};

struct int3472_gpio_regulator {
	/* SUPPLY_MAP_COUNT * 2 to make room for second sensor mappings */
	struct regulator_consumer_supply supply_map[GPIO_REGULATOR_SUPPLY_MAP_COUNT * 2];
	char supply_name_upper[GPIO_SUPPLY_NAME_LENGTH];
	char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
	struct gpio_desc *ena_gpio;
	struct regulator_dev *rdev;
	struct regulator_desc rdesc;
};

struct int3472_discrete_device {
	struct acpi_device *adev;
	struct device *dev;
	struct acpi_device *sensor;
	const char *sensor_name;

	struct int3472_gpio_regulator regulators[INT3472_MAX_REGULATORS];

	struct int3472_clock {
		struct clk *clk;
		struct clk_hw clk_hw;
		struct clk_lookup *cl;
		struct gpio_desc *ena_gpio;
		u32 frequency;
		u8 imgclk_index;
	} clock;

	struct int3472_pled {
		struct led_classdev classdev;
		struct led_lookup_data lookup;
		char name[INT3472_LED_MAX_NAME_LEN];
		struct gpio_desc *gpio;
	} pled;

	struct int3472_discrete_quirks quirks;

	unsigned int ngpios; /* how many GPIOs have we seen */
	unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
	unsigned int n_regulator_gpios; /* how many have we mapped to a regulator */
	struct gpiod_lookup_table gpios;
};

extern const struct dmi_system_id skl_int3472_discrete_quirks[];

union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev,
					       char *id);
int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb);
int skl_int3472_get_sensor_adev_and_name(struct device *dev,
					 struct acpi_device **sensor_adev_ret,
					 const char **name_ret);

int int3472_discrete_parse_crs(struct int3472_discrete_device *int3472);
void int3472_discrete_cleanup(struct int3472_discrete_device *int3472);

int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472,
				    struct gpio_desc *gpio);
int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472);
void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472);

int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
				   struct gpio_desc *gpio,
				   unsigned int enable_time,
				   const char *supply_name,
				   const char *second_sensor);
void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472);

int skl_int3472_register_pled(struct int3472_discrete_device *int3472, struct gpio_desc *gpio);
void skl_int3472_unregister_pled(struct int3472_discrete_device *int3472);

#endif