Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ov5693 and intel-skl-int3472 drivers #86

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions drivers/platform/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,8 @@ config INTEL_CHT_INT33FE
device and CONFIG_TYPEC_FUSB302=m and CONFIG_BATTERY_MAX17042=m
for Type-C device.

source "drivers/platform/x86/intel-int3472/Kconfig"

config INTEL_HID_EVENT
tristate "INTEL HID Event"
depends on ACPI
Expand Down
2 changes: 1 addition & 1 deletion drivers/platform/x86/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o
obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o
obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o

obj-$(CONFIG_INTEL_SKL_INT3472) += intel-int3472/
obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o

# MSI
Expand Down
31 changes: 31 additions & 0 deletions drivers/platform/x86/intel-int3472/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
config INTEL_SKL_INT3472
tristate "Intel SkyLake ACPI INT3472 Driver"
depends on ACPI
depends on REGULATOR
depends on GPIOLIB
depends on COMMON_CLK && CLKDEV_LOOKUP
depends on I2C
select MFD_CORE
select REGMAP_I2C
help
This driver adds support for the INT3472 ACPI devices found on some
Intel SkyLake devices.

The INT3472 is an Intel camera power controller, a logical device
found on some Skylake-based systems that can map to different
hardware devices depending on the platform. On machines
designed for Chrome OS, it maps to a TPS68470 camera PMIC. On
machines designed for Windows, it maps to either a TP68470
camera PMIC, a uP6641Q sensor PMIC, or a set of discrete GPIOs
and power gates.

If your device was designed for Chrome OS, this driver will provide
an ACPI OpRegion, which must be available before any of the devices
using it are probed. For this reason, you should select Y if your
device was designed for ChromeOS. For the same reason the
I2C_DESIGNWARE_PLATFORM option must be set to Y too.

Say Y or M here if you have a SkyLake device designed for use
with Windows or ChromeOS. Say N here if you are not sure.

The module will be named "intel-skl-int3472"
4 changes: 4 additions & 0 deletions drivers/platform/x86/intel-int3472/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472.o
intel_skl_int3472-objs := intel_skl_int3472_common.o \
intel_skl_int3472_discrete.o \
intel_skl_int3472_tps68470.o
106 changes: 106 additions & 0 deletions drivers/platform/x86/intel-int3472/intel_skl_int3472_common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// SPDX-License-Identifier: GPL-2.0
/* Author: Dan Scally <djrscally@gmail.com> */

#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#include "intel_skl_int3472_common.h"

union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev,
char *id)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_handle handle = adev->handle;
union acpi_object *obj;
acpi_status status;

status = acpi_evaluate_object(handle, id, NULL, &buffer);
if (ACPI_FAILURE(status))
return ERR_PTR(-ENODEV);

obj = buffer.pointer;
if (!obj)
return ERR_PTR(-ENODEV);

if (obj->type != ACPI_TYPE_BUFFER) {
dev_err(&adev->dev, "%s object is not an ACPI buffer\n", id);
kfree(obj);
return ERR_PTR(-EINVAL);
}

return obj;
}

int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb)
{
union acpi_object *obj;
int ret = 0;

obj = skl_int3472_get_acpi_buffer(adev, "CLDB");
if (IS_ERR(obj))
return PTR_ERR(obj);

if (obj->buffer.length > sizeof(*cldb)) {
dev_err(&adev->dev, "The CLDB buffer is too large\n");
ret = -EINVAL;
goto out_free_obj;
}

memcpy(cldb, obj->buffer.pointer, obj->buffer.length);

out_free_obj:
kfree(obj);
return ret;
}

static const struct acpi_device_id int3472_device_id[] = {
{ "INT3472", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, int3472_device_id);

static struct platform_driver int3472_discrete = {
.driver = {
.name = "int3472-discrete",
.acpi_match_table = int3472_device_id,
},
.probe = skl_int3472_discrete_probe,
.remove = skl_int3472_discrete_remove,
};

static struct i2c_driver int3472_tps68470 = {
.driver = {
.name = "int3472-tps68470",
.acpi_match_table = int3472_device_id,
},
.probe_new = skl_int3472_tps68470_probe,
};

static int skl_int3472_init(void)
{
int ret = 0;

ret = platform_driver_register(&int3472_discrete);
if (ret)
return ret;

ret = i2c_register_driver(THIS_MODULE, &int3472_tps68470);
if (ret)
platform_driver_unregister(&int3472_discrete);

return ret;
}
module_init(skl_int3472_init);

static void skl_int3472_exit(void)
{
platform_driver_unregister(&int3472_discrete);
i2c_del_driver(&int3472_tps68470);
}
module_exit(skl_int3472_exit);

MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Device Driver");
MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
MODULE_LICENSE("GPL v2");
110 changes: 110 additions & 0 deletions drivers/platform/x86/intel-int3472/intel_skl_int3472_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Author: Dan Scally <djrscally@gmail.com> */

#ifndef _INTEL_SKL_INT3472_H
#define _INTEL_SKL_INT3472_H

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

/* 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_PDEV_MAX_NAME_LEN 23
#define INT3472_MAX_SENSOR_GPIOS 3

#define GPIO_REGULATOR_NAME_LENGTH 21
#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH 9

#define CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET 86

#define INT3472_REGULATOR(_name, _supply, _ops) \
(const struct regulator_desc) { \
.name = _name, \
.supply_name = _supply, \
.type = REGULATOR_VOLTAGE, \
.ops = _ops, \
.owner = THIS_MODULE, \
}

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

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

struct platform_device;
struct i2c_client;
struct acpi_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[28];
};

struct int3472_gpio_function_remap {
char *documented;
char *actual;
};

struct int3472_sensor_config {
const char *sensor_module_name;
struct regulator_consumer_supply supply_map;
const struct int3472_gpio_function_remap *function_maps;
};

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

struct int3472_sensor_config *sensor_config;

struct int3472_gpio_regulator {
char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
struct gpio_desc *gpio;
struct regulator_dev *rdev;
struct regulator_desc rdesc;
} regulator;

struct int3472_gpio_clock {
struct clk *clk;
struct clk_hw clk_hw;
struct clk_lookup *cl;
struct gpio_desc *ena_gpio;
struct gpio_desc *led_gpio;
u32 frequency;
} clock;

unsigned int n_gpios; /* how many GPIOs have we seen */
unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
struct gpiod_lookup_table gpios;
};

int skl_int3472_discrete_probe(struct platform_device *pdev);
int skl_int3472_discrete_remove(struct platform_device *pdev);
int skl_int3472_tps68470_probe(struct i2c_client *client);
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);

#endif
Loading