Signed tag for the immutable platform-drivers-x86-int3472 branch

This branch contains 5.16-rc1 + the pending ACPI/i2c, tps68570 platform_data
 and INT3472 driver patches.
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEEuvA7XScYQRpenhd+kuxHeUQDJ9wFAmG6YLQUHGhkZWdvZWRl
 QHJlZGhhdC5jb20ACgkQkuxHeUQDJ9zwGwf8Csb4wXyc3duBlnX/9jO9REDVKTN9
 HhmU2KQm29g10dN2nlFXEOG16xAy8zt3BE7QwniL/R5sUsKTCAEugY8Aqq/4+lFA
 vTU+YR9YqZFmEDGMfDngHeh9ZvSWIJS7IEXthxCkgGVhrd2Wl50jKTjVyq1RIDKv
 a7B4fOhguFv95xRlnXK+yoVUU7zZPWAgxyCqV0E0JEi8aWE8Y483IRCzcDEyJeDa
 HkgZLVwD9l3WQ4uZllVg1q5jfSprHwBa8dFxgcd6mOOYaKowiJ+GjnvnXOto5X72
 zsODBJH15VzfVXF5cAqIvzN6nAFR8Mxieei+21iFyUD/Ps1vfWlodFHH2w==
 =Q1N9
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmG6ZWwACgkQJNaLcl1U
 h9DPAwf/VhoTT8p5SjcbzAwIHEdVbb3OgGiTIZE9i70edvkUVmSYzowAeyWqCCP6
 IQ21qrL07h6LO76cE6gWjXutYSshQm4WBDThNrT1LigN99bCb4WNTodWK7A4FKgv
 RK7McVVFTecVItHP1L2Tw3JLIH5q6pKsVZEytvzvonD9ZE+9T0uJ3+nOhWtX2DPJ
 dIIEjb8kxta3sZIBLi3bVTdDQDRAsKuLf7/dFFFvIupmloB7a5thDrpqglfX5pVw
 eDzIywMUSsoEef7r4uFP4XOxXEtRN1+20jGmm3Y+5Qsi5ICkvUwVw3NQYr5W2reN
 lehVNxrGfxlbvnoS8ieAZfFiR9SDqA==
 =CXOz
 -----END PGP SIGNATURE-----

Merge tag 'platform-drivers-x86-int3472-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86 into regulator-5.17

Signed tag for the immutable platform-drivers-x86-int3472 branch

This branch contains 5.16-rc1 + the pending ACPI/i2c, tps68570 platform_data
and INT3472 driver patches required so that the tps68570 regulator
driver can be applied.
This commit is contained in:
Mark Brown 2021-12-15 21:59:33 +00:00
commit 13aad3431e
14 changed files with 473 additions and 161 deletions

View file

@ -797,6 +797,12 @@ static const char * const acpi_ignore_dep_ids[] = {
NULL
};
/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */
static const char * const acpi_honor_dep_ids[] = {
"INT3472", /* Camera sensor PMIC / clk and regulator info */
NULL
};
static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
{
struct acpi_device *device = NULL;
@ -1762,8 +1768,12 @@ static void acpi_scan_dep_init(struct acpi_device *adev)
struct acpi_dep_data *dep;
list_for_each_entry(dep, &acpi_dep_list, node) {
if (dep->consumer == adev->handle)
if (dep->consumer == adev->handle) {
if (dep->honor_dep)
adev->flags.honor_deps = 1;
adev->dep_unmet++;
}
}
}
@ -1967,7 +1977,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
for (count = 0, i = 0; i < dep_devices.count; i++) {
struct acpi_device_info *info;
struct acpi_dep_data *dep;
bool skip;
bool skip, honor_dep;
status = acpi_get_object_info(dep_devices.handles[i], &info);
if (ACPI_FAILURE(status)) {
@ -1976,6 +1986,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
}
skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids);
honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids);
kfree(info);
if (skip)
@ -1989,6 +2000,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
dep->supplier = dep_devices.handles[i];
dep->consumer = handle;
dep->honor_dep = honor_dep;
mutex_lock(&acpi_dep_list_lock);
list_add_tail(&dep->node , &acpi_dep_list);
@ -2155,8 +2167,8 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
register_dock_dependent_device(device, ejd);
acpi_bus_get_status(device);
/* Skip devices that are not present. */
if (!acpi_device_is_present(device)) {
/* Skip devices that are not ready for enumeration (e.g. not present) */
if (!acpi_dev_ready_for_enumeration(device)) {
device->flags.initialized = false;
acpi_device_clear_enumerated(device);
device->flags.power_manageable = 0;
@ -2318,6 +2330,23 @@ void acpi_dev_clear_dependencies(struct acpi_device *supplier)
}
EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies);
/**
* acpi_dev_ready_for_enumeration - Check if the ACPI device is ready for enumeration
* @device: Pointer to the &struct acpi_device to check
*
* Check if the device is present and has no unmet dependencies.
*
* Return true if the device is ready for enumeratino. Otherwise, return false.
*/
bool acpi_dev_ready_for_enumeration(const struct acpi_device *device)
{
if (device->flags.honor_deps && device->dep_unmet)
return false;
return acpi_device_is_present(device);
}
EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration);
/**
* acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier
* @supplier: Pointer to the dependee device

View file

@ -144,9 +144,12 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
struct list_head resource_list;
int ret;
if (acpi_bus_get_status(adev) || !adev->status.present)
if (acpi_bus_get_status(adev))
return -EINVAL;
if (!acpi_dev_ready_for_enumeration(adev))
return -ENODEV;
if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0)
return -ENODEV;
@ -473,8 +476,8 @@ struct notifier_block i2c_acpi_notifier = {
};
/**
* i2c_acpi_new_device - Create i2c-client for the Nth I2cSerialBus resource
* @dev: Device owning the ACPI resources to get the client from
* i2c_acpi_new_device_by_fwnode - Create i2c-client for the Nth I2cSerialBus resource
* @fwnode: fwnode with the ACPI resources to get the client from
* @index: Index of ACPI resource to get
* @info: describes the I2C device; note this is modified (addr gets set)
* Context: can sleep
@ -490,15 +493,20 @@ struct notifier_block i2c_acpi_notifier = {
* Returns a pointer to the new i2c-client, or error pointer in case of failure.
* Specifically, -EPROBE_DEFER is returned if the adapter is not found.
*/
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
struct i2c_board_info *info)
struct i2c_client *i2c_acpi_new_device_by_fwnode(struct fwnode_handle *fwnode,
int index,
struct i2c_board_info *info)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
struct i2c_acpi_lookup lookup;
struct i2c_adapter *adapter;
struct acpi_device *adev;
LIST_HEAD(resource_list);
int ret;
adev = to_acpi_device_node(fwnode);
if (!adev)
return ERR_PTR(-ENODEV);
memset(&lookup, 0, sizeof(lookup));
lookup.info = info;
lookup.device_handle = acpi_device_handle(adev);
@ -520,7 +528,7 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
return i2c_new_client_device(adapter, info);
}
EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
EXPORT_SYMBOL_GPL(i2c_acpi_new_device_by_fwnode);
bool i2c_acpi_waive_d0_probe(struct device *dev)
{

View file

@ -1,5 +1,4 @@
obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472.o
intel_skl_int3472-y := intel_skl_int3472_common.o \
intel_skl_int3472_discrete.o \
intel_skl_int3472_tps68470.o \
intel_skl_int3472_clk_and_regulator.o
obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472_discrete.o \
intel_skl_int3472_tps68470.o
intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o common.o
intel_skl_int3472_tps68470-y := tps68470.o tps68470_board_data.o common.o

View file

@ -9,7 +9,7 @@
#include <linux/regulator/driver.h>
#include <linux/slab.h>
#include "intel_skl_int3472_common.h"
#include "common.h"
/*
* The regulators have to have .ops to be valid, but the only ops we actually

View file

@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0
/* Author: Dan Scally <djrscally@gmail.com> */
#include <linux/acpi.h>
#include <linux/slab.h>
#include "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) {
acpi_handle_err(handle, "%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;
obj = skl_int3472_get_acpi_buffer(adev, "CLDB");
if (IS_ERR(obj))
return PTR_ERR(obj);
if (obj->buffer.length > sizeof(*cldb)) {
acpi_handle_err(adev->handle, "The CLDB buffer is too large\n");
ret = -EINVAL;
goto out_free_obj;
}
memcpy(cldb, obj->buffer.pointer, obj->buffer.length);
ret = 0;
out_free_obj:
kfree(obj);
return ret;
}
/* sensor_adev_ret may be NULL, name_ret must not be NULL */
int skl_int3472_get_sensor_adev_and_name(struct device *dev,
struct acpi_device **sensor_adev_ret,
const char **name_ret)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
struct acpi_device *sensor;
int ret = 0;
sensor = acpi_dev_get_first_consumer_dev(adev);
if (!sensor) {
dev_err(dev, "INT3472 seems to have no dependents.\n");
return -ENODEV;
}
*name_ret = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT,
acpi_dev_name(sensor));
if (!*name_ret)
ret = -ENOMEM;
if (ret == 0 && sensor_adev_ret)
*sensor_adev_ret = sensor;
else
acpi_dev_put(sensor);
return ret;
}

View file

@ -105,12 +105,12 @@ struct int3472_discrete_device {
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);
int skl_int3472_get_sensor_adev_and_name(struct device *dev,
struct acpi_device **sensor_adev_ret,
const char **name_ret);
int skl_int3472_register_clock(struct int3472_discrete_device *int3472);
void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472);

View file

@ -14,7 +14,7 @@
#include <linux/platform_device.h>
#include <linux/uuid.h>
#include "intel_skl_int3472_common.h"
#include "common.h"
/*
* 79234640-9e10-4fea-a5c1-b5aa8b19756f
@ -332,7 +332,9 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472)
return 0;
}
int skl_int3472_discrete_probe(struct platform_device *pdev)
static int skl_int3472_discrete_remove(struct platform_device *pdev);
static int skl_int3472_discrete_probe(struct platform_device *pdev)
{
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
struct int3472_discrete_device *int3472;
@ -361,19 +363,10 @@ int skl_int3472_discrete_probe(struct platform_device *pdev)
int3472->dev = &pdev->dev;
platform_set_drvdata(pdev, int3472);
int3472->sensor = acpi_dev_get_first_consumer_dev(adev);
if (!int3472->sensor) {
dev_err(&pdev->dev, "INT3472 seems to have no dependents.\n");
return -ENODEV;
}
int3472->sensor_name = devm_kasprintf(int3472->dev, GFP_KERNEL,
I2C_DEV_NAME_FORMAT,
acpi_dev_name(int3472->sensor));
if (!int3472->sensor_name) {
ret = -ENOMEM;
goto err_put_sensor;
}
ret = skl_int3472_get_sensor_adev_and_name(&pdev->dev, &int3472->sensor,
&int3472->sensor_name);
if (ret)
return ret;
/*
* Initialising this list means we can call gpiod_remove_lookup_table()
@ -387,15 +380,11 @@ int skl_int3472_discrete_probe(struct platform_device *pdev)
return ret;
}
acpi_dev_clear_dependencies(adev);
return 0;
err_put_sensor:
acpi_dev_put(int3472->sensor);
return ret;
}
int skl_int3472_discrete_remove(struct platform_device *pdev)
static int skl_int3472_discrete_remove(struct platform_device *pdev)
{
struct int3472_discrete_device *int3472 = platform_get_drvdata(pdev);
@ -411,3 +400,23 @@ int skl_int3472_discrete_remove(struct platform_device *pdev)
return 0;
}
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,
};
module_platform_driver(int3472_discrete);
MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Discrete Device Driver");
MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
MODULE_LICENSE("GPL v2");

View file

@ -1,106 +0,0 @@
// 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) {
acpi_handle_err(handle, "%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;
obj = skl_int3472_get_acpi_buffer(adev, "CLDB");
if (IS_ERR(obj))
return PTR_ERR(obj);
if (obj->buffer.length > sizeof(*cldb)) {
acpi_handle_err(adev->handle, "The CLDB buffer is too large\n");
ret = -EINVAL;
goto out_free_obj;
}
memcpy(cldb, obj->buffer.pointer, obj->buffer.length);
ret = 0;
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;
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");

View file

@ -2,27 +2,27 @@
/* Author: Dan Scally <djrscally@gmail.com> */
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps68470.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tps68470.h>
#include <linux/regmap.h>
#include <linux/string.h>
#include "intel_skl_int3472_common.h"
#include "common.h"
#include "tps68470.h"
#define DESIGNED_FOR_CHROMEOS 1
#define DESIGNED_FOR_WINDOWS 2
#define TPS68470_WIN_MFD_CELL_COUNT 3
static const struct mfd_cell tps68470_cros[] = {
{ .name = "tps68470-gpio" },
{ .name = "tps68470_pmic_opregion" },
};
static const struct mfd_cell tps68470_win[] = {
{ .name = "tps68470-gpio" },
{ .name = "tps68470-clk" },
{ .name = "tps68470-regulator" },
};
static const struct regmap_config tps68470_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@ -95,13 +95,21 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev)
return DESIGNED_FOR_WINDOWS;
}
int skl_int3472_tps68470_probe(struct i2c_client *client)
static int skl_int3472_tps68470_probe(struct i2c_client *client)
{
struct acpi_device *adev = ACPI_COMPANION(&client->dev);
const struct int3472_tps68470_board_data *board_data;
struct tps68470_clk_platform_data clk_pdata = {};
struct mfd_cell *cells;
struct regmap *regmap;
int device_type;
int ret;
ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL,
&clk_pdata.consumer_dev_name);
if (ret)
return ret;
regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Failed to create regmap: %ld\n", PTR_ERR(regmap));
@ -119,9 +127,38 @@ int skl_int3472_tps68470_probe(struct i2c_client *client)
device_type = skl_int3472_tps68470_calc_type(adev);
switch (device_type) {
case DESIGNED_FOR_WINDOWS:
board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
if (!board_data)
return dev_err_probe(&client->dev, -ENODEV, "No board-data found for this model\n");
cells = kcalloc(TPS68470_WIN_MFD_CELL_COUNT, sizeof(*cells), GFP_KERNEL);
if (!cells)
return -ENOMEM;
/*
* The order of the cells matters here! The clk must be first
* because the regulator depends on it. The gpios must be last,
* acpi_gpiochip_add() calls acpi_dev_clear_dependencies() and
* the clk + regulators must be ready when this happens.
*/
cells[0].name = "tps68470-clk";
cells[0].platform_data = &clk_pdata;
cells[0].pdata_size = sizeof(clk_pdata);
cells[1].name = "tps68470-regulator";
cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata;
cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data);
cells[2].name = "tps68470-gpio";
gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table);
ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
tps68470_win, ARRAY_SIZE(tps68470_win),
cells, TPS68470_WIN_MFD_CELL_COUNT,
NULL, 0, NULL);
kfree(cells);
if (ret)
gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
break;
case DESIGNED_FOR_CHROMEOS:
ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
@ -133,5 +170,42 @@ int skl_int3472_tps68470_probe(struct i2c_client *client)
return device_type;
}
/*
* No acpi_dev_clear_dependencies() here, since the acpi_gpiochip_add()
* for the GPIO cell already does this.
*/
return ret;
}
static int skl_int3472_tps68470_remove(struct i2c_client *client)
{
const struct int3472_tps68470_board_data *board_data;
board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
if (board_data)
gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
return 0;
}
static const struct acpi_device_id int3472_device_id[] = {
{ "INT3472", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, int3472_device_id);
static struct i2c_driver int3472_tps68470 = {
.driver = {
.name = "int3472-tps68470",
.acpi_match_table = int3472_device_id,
},
.probe_new = skl_int3472_tps68470_probe,
.remove = skl_int3472_tps68470_remove,
};
module_i2c_driver(int3472_tps68470);
MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI TPS68470 Device Driver");
MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
MODULE_LICENSE("GPL v2");
MODULE_SOFTDEP("pre: clk-tps68470 tps68470-regulator");

View file

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* TI TPS68470 PMIC platform data definition.
*
* Copyright (c) 2021 Red Hat Inc.
*
* Red Hat authors:
* Hans de Goede <hdegoede@redhat.com>
*/
#ifndef _INTEL_SKL_INT3472_TPS68470_H
#define _INTEL_SKL_INT3472_TPS68470_H
struct gpiod_lookup_table;
struct tps68470_regulator_platform_data;
struct int3472_tps68470_board_data {
const char *dev_name;
struct gpiod_lookup_table *tps68470_gpio_lookup_table;
const struct tps68470_regulator_platform_data *tps68470_regulator_pdata;
};
const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name);
#endif

View file

@ -0,0 +1,145 @@
// SPDX-License-Identifier: GPL-2.0
/*
* TI TPS68470 PMIC platform data definition.
*
* Copyright (c) 2021 Dan Scally <djrscally@gmail.com>
* Copyright (c) 2021 Red Hat Inc.
*
* Red Hat authors:
* Hans de Goede <hdegoede@redhat.com>
*/
#include <linux/dmi.h>
#include <linux/gpio/machine.h>
#include <linux/platform_data/tps68470.h>
#include <linux/regulator/machine.h>
#include "tps68470.h"
static struct regulator_consumer_supply int347a_core_consumer_supplies[] = {
REGULATOR_SUPPLY("dvdd", "i2c-INT347A:00"),
};
static struct regulator_consumer_supply int347a_ana_consumer_supplies[] = {
REGULATOR_SUPPLY("avdd", "i2c-INT347A:00"),
};
static struct regulator_consumer_supply int347a_vcm_consumer_supplies[] = {
REGULATOR_SUPPLY("vdd", "i2c-INT347A:00-VCM"),
};
static struct regulator_consumer_supply int347a_vsio_consumer_supplies[] = {
REGULATOR_SUPPLY("dovdd", "i2c-INT347A:00"),
REGULATOR_SUPPLY("vsio", "i2c-INT347A:00-VCM"),
};
static const struct regulator_init_data surface_go_tps68470_core_reg_init_data = {
.constraints = {
.min_uV = 1200000,
.max_uV = 1200000,
.apply_uV = true,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(int347a_core_consumer_supplies),
.consumer_supplies = int347a_core_consumer_supplies,
};
static const struct regulator_init_data surface_go_tps68470_ana_reg_init_data = {
.constraints = {
.min_uV = 2815200,
.max_uV = 2815200,
.apply_uV = true,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(int347a_ana_consumer_supplies),
.consumer_supplies = int347a_ana_consumer_supplies,
};
static const struct regulator_init_data surface_go_tps68470_vcm_reg_init_data = {
.constraints = {
.min_uV = 2815200,
.max_uV = 2815200,
.apply_uV = true,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(int347a_vcm_consumer_supplies),
.consumer_supplies = int347a_vcm_consumer_supplies,
};
/* Ensure the always-on VIO regulator has the same voltage as VSIO */
static const struct regulator_init_data surface_go_tps68470_vio_reg_init_data = {
.constraints = {
.min_uV = 1800600,
.max_uV = 1800600,
.apply_uV = true,
.always_on = true,
},
};
static const struct regulator_init_data surface_go_tps68470_vsio_reg_init_data = {
.constraints = {
.min_uV = 1800600,
.max_uV = 1800600,
.apply_uV = true,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(int347a_vsio_consumer_supplies),
.consumer_supplies = int347a_vsio_consumer_supplies,
};
static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = {
.reg_init_data = {
[TPS68470_CORE] = &surface_go_tps68470_core_reg_init_data,
[TPS68470_ANA] = &surface_go_tps68470_ana_reg_init_data,
[TPS68470_VCM] = &surface_go_tps68470_vcm_reg_init_data,
[TPS68470_VIO] = &surface_go_tps68470_vio_reg_init_data,
[TPS68470_VSIO] = &surface_go_tps68470_vsio_reg_init_data,
},
};
static struct gpiod_lookup_table surface_go_tps68470_gpios = {
.dev_id = "i2c-INT347A:00",
.table = {
GPIO_LOOKUP("tps68470-gpio", 9, "reset", GPIO_ACTIVE_LOW),
GPIO_LOOKUP("tps68470-gpio", 7, "powerdown", GPIO_ACTIVE_LOW)
}
};
static const struct int3472_tps68470_board_data surface_go_tps68470_board_data = {
.dev_name = "i2c-INT3472:05",
.tps68470_gpio_lookup_table = &surface_go_tps68470_gpios,
.tps68470_regulator_pdata = &surface_go_tps68470_pdata,
};
static const struct dmi_system_id int3472_tps68470_board_data_table[] = {
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go"),
},
.driver_data = (void *)&surface_go_tps68470_board_data,
},
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go 2"),
},
.driver_data = (void *)&surface_go_tps68470_board_data,
},
{ }
};
const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name)
{
const struct int3472_tps68470_board_data *board_data;
const struct dmi_system_id *match;
for (match = dmi_first_match(int3472_tps68470_board_data_table);
match;
match = dmi_first_match(match + 1)) {
board_data = match->driver_data;
if (strcmp(board_data->dev_name, dev_name) == 0)
return board_data;
}
return NULL;
}

View file

@ -202,7 +202,8 @@ struct acpi_device_flags {
u32 coherent_dma:1;
u32 cca_seen:1;
u32 enumeration_by_parent:1;
u32 reserved:19;
u32 honor_deps:1;
u32 reserved:18;
};
/* File System */
@ -285,6 +286,7 @@ struct acpi_dep_data {
struct list_head node;
acpi_handle supplier;
acpi_handle consumer;
bool honor_dep;
};
/* Performance Management */
@ -693,6 +695,7 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2);
void acpi_dev_clear_dependencies(struct acpi_device *supplier);
bool acpi_dev_ready_for_enumeration(const struct acpi_device *device);
struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier);
struct acpi_device *
acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv);

View file

@ -1025,8 +1025,9 @@ bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
struct acpi_resource_i2c_serialbus **i2c);
int i2c_acpi_client_count(struct acpi_device *adev);
u32 i2c_acpi_find_bus_speed(struct device *dev);
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
struct i2c_board_info *info);
struct i2c_client *i2c_acpi_new_device_by_fwnode(struct fwnode_handle *fwnode,
int index,
struct i2c_board_info *info);
struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle);
bool i2c_acpi_waive_d0_probe(struct device *dev);
#else
@ -1043,8 +1044,9 @@ static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
{
return 0;
}
static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
int index, struct i2c_board_info *info)
static inline struct i2c_client *i2c_acpi_new_device_by_fwnode(
struct fwnode_handle *fwnode, int index,
struct i2c_board_info *info)
{
return ERR_PTR(-ENODEV);
}
@ -1058,4 +1060,11 @@ static inline bool i2c_acpi_waive_d0_probe(struct device *dev)
}
#endif /* CONFIG_ACPI */
static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
int index,
struct i2c_board_info *info)
{
return i2c_acpi_new_device_by_fwnode(dev_fwnode(dev), index, info);
}
#endif /* _LINUX_I2C_H */

View file

@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* TI TPS68470 PMIC platform data definition.
*
* Copyright (c) 2021 Red Hat Inc.
*
* Red Hat authors:
* Hans de Goede <hdegoede@redhat.com>
*/
#ifndef __PDATA_TPS68470_H
#define __PDATA_TPS68470_H
enum tps68470_regulators {
TPS68470_CORE,
TPS68470_ANA,
TPS68470_VCM,
TPS68470_VIO,
TPS68470_VSIO,
TPS68470_AUX1,
TPS68470_AUX2,
TPS68470_NUM_REGULATORS
};
struct regulator_init_data;
struct tps68470_regulator_platform_data {
const struct regulator_init_data *reg_init_data[TPS68470_NUM_REGULATORS];
};
struct tps68470_clk_platform_data {
const char *consumer_dev_name;
const char *consumer_con_id;
};
#endif