#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/efi.h>
#include <linux/gpio/machine.h>
#include <linux/gpio/property.h>
#include <linux/input-event-codes.h>
#include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h>
#include <linux/mfd/intel_soc_pmic.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/machine.h>
#include <linux/platform_data/lp855x.h>
#include <linux/platform_device.h>
#include <linux/power/bq24190_charger.h>
#include <linux/reboot.h>
#include <linux/rmi.h>
#include <linux/spi/spi.h>
#include "shared-psy-info.h"
#include "x86-android-tablets.h"
static struct lp855x_platform_data lenovo_lp8557_pwm_and_reg_pdata = {
.device_control = 0x86,
.initial_brightness = 128,
};
static struct lp855x_platform_data lenovo_lp8557_reg_only_pdata = {
.device_control = 0x85,
.initial_brightness = 128,
};
static const struct software_node arizona_gpiochip_node = {
.name = "arizona",
};
static const struct software_node crystalcove_gpiochip_node = {
.name = "gpio_crystalcove",
};
static const struct property_entry lenovo_yb1_x90_goodix_props[] = {
PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[1], 53, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("irq-gpios", &cherryview_gpiochip_nodes[1], 56, GPIO_ACTIVE_HIGH),
{ }
};
static const struct software_node lenovo_yb1_x90_goodix_node = {
.properties = lenovo_yb1_x90_goodix_props,
};
static const struct property_entry lenovo_yb1_x90_wacom_props[] = {
PROPERTY_ENTRY_U32("hid-descr-addr", 0x0001),
PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 150),
PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[0], 82, GPIO_ACTIVE_LOW),
{ }
};
static const struct software_node lenovo_yb1_x90_wacom_node = {
.properties = lenovo_yb1_x90_wacom_props,
};
static const struct property_entry lenovo_yb1_x90_hideep_ts_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1200),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
PROPERTY_ENTRY_U32("touchscreen-max-pressure", 16384),
PROPERTY_ENTRY_BOOL("hideep,force-native-protocol"),
PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[0], 7, GPIO_ACTIVE_LOW),
{ }
};
static const struct software_node lenovo_yb1_x90_hideep_ts_node = {
.properties = lenovo_yb1_x90_hideep_ts_props,
};
static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst = {
{
.board_info = {
.type = "bq27542",
.addr = 0x55,
.dev_name = "bq27542",
.swnode = &fg_bq25890_supply_node,
},
.adapter_path = "\\_SB_.PCI0.I2C1",
}, {
.board_info = {
.type = "GDIX1001:00",
.addr = 0x14,
.dev_name = "goodix_ts",
.swnode = &lenovo_yb1_x90_goodix_node,
},
.adapter_path = "\\_SB_.PCI0.I2C2",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_GPIOINT,
.chip = "INT33FF:01",
.index = 56,
.trigger = ACPI_EDGE_SENSITIVE,
.polarity = ACPI_ACTIVE_LOW,
.con_id = "goodix_ts_irq",
.free_gpio = true,
},
}, {
.board_info = {
.type = "hid-over-i2c",
.addr = 0x09,
.dev_name = "wacom",
.swnode = &lenovo_yb1_x90_wacom_node,
},
.adapter_path = "\\_SB_.PCI0.I2C4",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_GPIOINT,
.chip = "INT33FF:01",
.index = 49,
.trigger = ACPI_LEVEL_SENSITIVE,
.polarity = ACPI_ACTIVE_LOW,
.con_id = "wacom_irq",
},
}, {
.board_info = {
.type = "lp8557",
.addr = 0x2c,
.dev_name = "lp8557",
.platform_data = &lenovo_lp8557_pwm_and_reg_pdata,
},
.adapter_path = "\\_SB_.PCI0.I2C4",
}, {
.board_info = {
.type = "hideep_ts",
.addr = 0x6c,
.dev_name = "hideep_ts",
.swnode = &lenovo_yb1_x90_hideep_ts_node,
},
.adapter_path = "\\_SB_.PCI0.I2C6",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_GPIOINT,
.chip = "INT33FF:03",
.index = 77,
.trigger = ACPI_LEVEL_SENSITIVE,
.polarity = ACPI_ACTIVE_LOW,
.con_id = "hideep_ts_irq",
},
},
};
static const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = {
{
.name = "yogabook-touch-kbd-digitizer-switch",
.id = PLATFORM_DEVID_NONE,
},
};
static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = {
{
.ctrl.acpi.hid = "8086228A",
.ctrl.acpi.uid = "1",
.ctrl_devname = "serial0",
.serdev_hid = "BCM2E1A",
},
};
static const struct software_node lenovo_lid_gpio_keys_node = {
.name = "lid_sw",
};
static const struct property_entry lenovo_yb1_x90_lid_props[] = {
PROPERTY_ENTRY_U32("linux,input-type", EV_SW),
PROPERTY_ENTRY_U32("linux,code", SW_LID),
PROPERTY_ENTRY_STRING("label", "lid_sw"),
PROPERTY_ENTRY_GPIO("gpios", &cherryview_gpiochip_nodes[2], 19, GPIO_ACTIVE_LOW),
PROPERTY_ENTRY_U32("debounce-interval", 50),
PROPERTY_ENTRY_BOOL("wakeup-source"),
{ }
};
static const struct software_node lenovo_yb1_x90_lid_node = {
.parent = &lenovo_lid_gpio_keys_node,
.properties = lenovo_yb1_x90_lid_props,
};
static const struct software_node *lenovo_yb1_x90_lid_swnodes[] = {
&lenovo_lid_gpio_keys_node,
&lenovo_yb1_x90_lid_node,
NULL
};
static int __init lenovo_yb1_x90_init(struct device *dev)
{
intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9f, 0x02, 0xff);
intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa1, 0x02, 0xff);
return 0;
}
const struct x86_dev_info lenovo_yogabook_x90_info __initconst = {
.i2c_client_info = lenovo_yb1_x90_i2c_clients,
.i2c_client_count = ARRAY_SIZE(lenovo_yb1_x90_i2c_clients),
.pdev_info = lenovo_yb1_x90_pdevs,
.pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs),
.serdev_info = lenovo_yb1_x90_serdevs,
.serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs),
.gpio_button_swnodes = lenovo_yb1_x90_lid_swnodes,
.gpiochip_type = X86_GPIOCHIP_CHERRYVIEW,
.init = lenovo_yb1_x90_init,
};
static const struct x86_i2c_client_info lenovo_yogabook_x91_i2c_clients[] __initconst = {
{
.board_info = {
.type = "bq27542",
.addr = 0x55,
.dev_name = "bq27542",
.swnode = &fg_bq25890_supply_node,
},
.adapter_path = "\\_SB_.PCI0.I2C1",
},
};
const struct x86_dev_info lenovo_yogabook_x91_info __initconst = {
.i2c_client_info = lenovo_yogabook_x91_i2c_clients,
.i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x91_i2c_clients),
};
static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = {
PROPERTY_ENTRY_STRING_ARRAY_LEN("supplied-from", tusb1211_chg_det_psy, 1),
PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
PROPERTY_ENTRY_BOOL("omit-battery-class"),
PROPERTY_ENTRY_BOOL("disable-reset"),
{ }
};
static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
.properties = lenovo_yoga_tab2_830_1050_bq24190_props,
};
static const struct property_entry lenovo_yoga_tab2_830_1050_lid_props[] = {
PROPERTY_ENTRY_U32("linux,input-type", EV_SW),
PROPERTY_ENTRY_U32("linux,code", SW_LID),
PROPERTY_ENTRY_STRING("label", "lid_sw"),
PROPERTY_ENTRY_GPIO("gpios", &baytrail_gpiochip_nodes[2], 26, GPIO_ACTIVE_LOW),
PROPERTY_ENTRY_U32("debounce-interval", 50),
PROPERTY_ENTRY_BOOL("wakeup-source"),
{ }
};
static const struct software_node lenovo_yoga_tab2_830_1050_lid_node = {
.parent = &lenovo_lid_gpio_keys_node,
.properties = lenovo_yoga_tab2_830_1050_lid_props,
};
static const struct software_node *lenovo_yoga_tab2_830_1050_lid_swnodes[] = {
&lenovo_lid_gpio_keys_node,
&lenovo_yoga_tab2_830_1050_lid_node,
NULL
};
static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { };
static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initdata = {
{
.board_info = {
.type = "lsm303d",
.addr = 0x1d,
.dev_name = "lsm303d",
},
.adapter_path = "\\_SB_.I2C5",
}, {
.board_info = {
.type = "al3320a",
.addr = 0x1c,
.dev_name = "al3320a",
},
.adapter_path = "\\_SB_.I2C5",
}, {
.board_info = {
.type = "bq24190",
.addr = 0x6b,
.dev_name = "bq24292i",
.swnode = &lenovo_yoga_tab2_830_1050_bq24190_node,
.platform_data = &bq24190_pdata,
},
.adapter_path = "\\_SB_.I2C1",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_GPIOINT,
.chip = "INT33FC:02",
.index = 2,
.trigger = ACPI_EDGE_SENSITIVE,
.polarity = ACPI_ACTIVE_HIGH,
.con_id = "bq24292i_irq",
},
}, {
.board_info = {
.type = "bq27541",
.addr = 0x55,
.dev_name = "bq27541",
.swnode = &fg_bq24190_supply_node,
},
.adapter_path = "\\_SB_.I2C1",
}, {
.board_info = {
.type = "rmi4_i2c",
.addr = 0x38,
.dev_name = "rmi4_i2c",
.platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
},
.adapter_path = "\\_SB_.I2C6",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_APIC,
.index = 0x45,
.trigger = ACPI_EDGE_SENSITIVE,
.polarity = ACPI_ACTIVE_HIGH,
},
}, {
.board_info = {
.type = "lp8557",
.addr = 0x2c,
.dev_name = "lp8557",
.platform_data = &lenovo_lp8557_pwm_and_reg_pdata,
},
.adapter_path = "\\_SB_.I2C3",
},
};
static const struct property_entry lenovo_yoga_tab2_830_1050_int3496_props[] __initconst = {
PROPERTY_ENTRY_GPIO("mux-gpios", &baytrail_gpiochip_nodes[2], 1, GPIO_ACTIVE_LOW),
PROPERTY_ENTRY_GPIO("id-gpios", &baytrail_gpiochip_nodes[2], 24, GPIO_ACTIVE_HIGH),
{ }
};
static const struct platform_device_info lenovo_yoga_tab2_830_1050_pdevs[] __initconst = {
{
.name = "intel-int3496",
.id = PLATFORM_DEVID_NONE,
.properties = lenovo_yoga_tab2_830_1050_int3496_props,
},
};
#define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00"
static const struct property_entry lenovo_yoga_tab2_830_1050_wm1502_props[] = {
PROPERTY_ENTRY_GPIO("reset-gpios",
&crystalcove_gpiochip_node, 3, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("wlf,ldoena-gpios",
&baytrail_gpiochip_nodes[1], 23, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("wlf,spkvdd-ena-gpios",
&arizona_gpiochip_node, 2, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("wlf,micd-pol-gpios",
&arizona_gpiochip_node, 4, GPIO_ACTIVE_LOW),
{ }
};
static const struct software_node lenovo_yoga_tab2_830_1050_wm5102 = {
.properties = lenovo_yoga_tab2_830_1050_wm1502_props,
};
static const struct software_node *lenovo_yoga_tab2_830_1050_swnodes[] = {
&crystalcove_gpiochip_node,
&arizona_gpiochip_node,
&lenovo_yoga_tab2_830_1050_wm5102,
&generic_lipo_hv_4v35_battery_node,
NULL
};
static int __init lenovo_yoga_tab2_830_1050_init(struct device *dev);
static void lenovo_yoga_tab2_830_1050_exit(void);
static const char * const lenovo_yoga_tab2_modules[] __initconst = {
"spi_pxa2xx_platform",
"bq24190_charger",
NULL
};
const struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = {
.i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients,
.i2c_client_count = ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients),
.pdev_info = lenovo_yoga_tab2_830_1050_pdevs,
.pdev_count = ARRAY_SIZE(lenovo_yoga_tab2_830_1050_pdevs),
.gpio_button_swnodes = lenovo_yoga_tab2_830_1050_lid_swnodes,
.swnode_group = lenovo_yoga_tab2_830_1050_swnodes,
.modules = lenovo_yoga_tab2_modules,
.gpiochip_type = X86_GPIOCHIP_BAYTRAIL,
.init = lenovo_yoga_tab2_830_1050_init,
.exit = lenovo_yoga_tab2_830_1050_exit,
};
static const char * const lenovo_yoga_tab2_830_lms303d_mount_matrix[] = {
"0", "1", "0",
"-1", "0", "0",
"0", "0", "1"
};
static const struct property_entry lenovo_yoga_tab2_830_lms303d_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", lenovo_yoga_tab2_830_lms303d_mount_matrix),
{ }
};
static const struct software_node lenovo_yoga_tab2_830_lms303d_node = {
.properties = lenovo_yoga_tab2_830_lms303d_props,
};
static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void)
{
struct gpio_desc *gpiod;
int ret;
ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, "yoga_bootstrap",
false, GPIOD_ASIS, &gpiod);
if (ret)
return ret;
ret = gpiod_get_value_cansleep(gpiod);
if (ret) {
pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n");
} else {
pr_info("detected Lenovo Yoga Tablet 2 830F/L\n");
lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true;
lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true;
lenovo_yoga_tab2_830_1050_i2c_clients[0].board_info.swnode =
&lenovo_yoga_tab2_830_lms303d_node;
}
return 0;
}
static const struct pinctrl_map lenovo_yoga_tab2_830_1050_codec_pinctrl_map =
PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk",
"INT33FC:02", "pmu_clk2_grp", "pmu_clk");
static struct device *lenovo_yoga_tab2_830_1050_codec_dev;
static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl;
static struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler;
static int __init lenovo_yoga_tab2_830_1050_init_codec(void)
{
struct device *codec_dev;
struct pinctrl *pinctrl;
int ret;
codec_dev = bus_find_device_by_name(&spi_bus_type, NULL,
LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
if (!codec_dev) {
pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
return -ENODEV;
}
ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1);
if (ret)
goto err_put_device;
pinctrl = pinctrl_get_select(codec_dev, "codec_32khz_clk");
if (IS_ERR(pinctrl)) {
ret = dev_err_probe(codec_dev, PTR_ERR(pinctrl), "selecting codec_32khz_clk\n");
goto err_unregister_mappings;
}
ret = device_add_software_node(codec_dev, &lenovo_yoga_tab2_830_1050_wm5102);
if (ret) {
dev_err_probe(codec_dev, ret, "adding software node\n");
goto err_put_pinctrl;
}
lenovo_yoga_tab2_830_1050_codec_dev = codec_dev;
lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl;
return 0;
err_put_pinctrl:
pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl);
err_unregister_mappings:
pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
err_put_device:
put_device(codec_dev);
return ret;
}
static int lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data *data)
{
efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
return NOTIFY_DONE;
}
static int __init lenovo_yoga_tab2_830_1050_init(struct device *dev)
{
int ret;
ret = lenovo_yoga_tab2_830_1050_init_touchscreen();
if (ret)
return ret;
ret = lenovo_yoga_tab2_830_1050_init_codec();
if (ret)
return ret;
lenovo_yoga_tab2_830_1050_sys_off_handler =
register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1,
lenovo_yoga_tab2_830_1050_power_off, NULL);
if (IS_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler))
return PTR_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler);
return 0;
}
static void lenovo_yoga_tab2_830_1050_exit(void)
{
unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler);
device_remove_software_node(lenovo_yoga_tab2_830_1050_codec_dev);
pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl);
pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
put_device(lenovo_yoga_tab2_830_1050_codec_dev);
}
static const char * const lc824206xa_chg_det_psy[] = { "lc824206xa-charger-detect" };
static const struct property_entry lenovo_yoga_tab2_1380_bq24190_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lc824206xa_chg_det_psy),
PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
PROPERTY_ENTRY_BOOL("omit-battery-class"),
PROPERTY_ENTRY_BOOL("disable-reset"),
{ }
};
static const struct software_node lenovo_yoga_tab2_1380_bq24190_node = {
.properties = lenovo_yoga_tab2_1380_bq24190_props,
};
static struct regulator_consumer_supply lc824206xa_consumer = {
.supply = "vbus",
.dev_name = "i2c-lc824206xa",
};
static const struct regulator_init_data lenovo_yoga_tab2_1380_bq24190_vbus_init_data = {
.constraints = {
.name = "bq24190_vbus",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.consumer_supplies = &lc824206xa_consumer,
.num_consumer_supplies = 1,
};
static struct bq24190_platform_data lenovo_yoga_tab2_1380_bq24190_pdata = {
.regulator_init_data = &lenovo_yoga_tab2_1380_bq24190_vbus_init_data,
};
static const struct property_entry lenovo_yoga_tab2_1380_lc824206xa_props[] = {
PROPERTY_ENTRY_BOOL("onnn,enable-miclr-for-dcp"),
{ }
};
static const struct software_node lenovo_yoga_tab2_1380_lc824206xa_node = {
.properties = lenovo_yoga_tab2_1380_lc824206xa_props,
};
static const char * const lenovo_yoga_tab2_1380_lms303d_mount_matrix[] = {
"0", "-1", "0",
"-1", "0", "0",
"0", "0", "1"
};
static const struct property_entry lenovo_yoga_tab2_1380_lms303d_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", lenovo_yoga_tab2_1380_lms303d_mount_matrix),
{ }
};
static const struct software_node lenovo_yoga_tab2_1380_lms303d_node = {
.properties = lenovo_yoga_tab2_1380_lms303d_props,
};
static const struct x86_i2c_client_info lenovo_yoga_tab2_1380_i2c_clients[] __initconst = {
{
.board_info = {
.type = "bq27541",
.addr = 0x55,
.dev_name = "bq27541",
.swnode = &fg_bq24190_supply_node,
},
.adapter_path = "\\_SB_.I2C1",
}, {
.board_info = {
.type = "bq24190",
.addr = 0x6b,
.dev_name = "bq24292i",
.swnode = &lenovo_yoga_tab2_1380_bq24190_node,
.platform_data = &lenovo_yoga_tab2_1380_bq24190_pdata,
},
.adapter_path = "\\_SB_.I2C1",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_GPIOINT,
.chip = "INT33FC:02",
.index = 2,
.trigger = ACPI_EDGE_SENSITIVE,
.polarity = ACPI_ACTIVE_HIGH,
.con_id = "bq24292i_irq",
},
}, {
.board_info = {
.type = "lp8557",
.addr = 0x2c,
.dev_name = "lp8557",
.platform_data = &lenovo_lp8557_pwm_and_reg_pdata,
},
.adapter_path = "\\_SB_.I2C3",
}, {
.board_info = {
.type = "lc824206xa",
.addr = 0x48,
.dev_name = "lc824206xa",
.swnode = &lenovo_yoga_tab2_1380_lc824206xa_node,
},
.adapter_path = "\\_SB_.I2C3",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_GPIOINT,
.chip = "INT33FC:02",
.index = 1,
.trigger = ACPI_LEVEL_SENSITIVE,
.polarity = ACPI_ACTIVE_LOW,
.con_id = "lc824206xa_irq",
},
}, {
.board_info = {
.type = "al3320a",
.addr = 0x1c,
.dev_name = "al3320a",
},
.adapter_path = "\\_SB_.I2C5",
}, {
.board_info = {
.type = "lsm303d",
.addr = 0x1d,
.dev_name = "lsm303d",
.swnode = &lenovo_yoga_tab2_1380_lms303d_node,
},
.adapter_path = "\\_SB_.I2C5",
}, {
.board_info = {
.type = "rmi4_i2c",
.addr = 0x38,
.dev_name = "rmi4_i2c",
.platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
},
.adapter_path = "\\_SB_.I2C6",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_APIC,
.index = 0x45,
.trigger = ACPI_EDGE_SENSITIVE,
.polarity = ACPI_ACTIVE_HIGH,
},
}
};
static const struct property_entry lenovo_yoga_tab2_1380_fc_props[] __initconst = {
PROPERTY_ENTRY_GPIO("uart3_txd-gpios", &baytrail_gpiochip_nodes[0], 57, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("uart3_rxd-gpios", &baytrail_gpiochip_nodes[0], 61, GPIO_ACTIVE_HIGH),
{ }
};
static const struct platform_device_info lenovo_yoga_tab2_1380_pdevs[] __initconst = {
{
.name = "lenovo-yoga-tab2-pro-1380-fastcharger",
.id = PLATFORM_DEVID_NONE,
.properties = lenovo_yoga_tab2_1380_fc_props,
},
};
static int __init lenovo_yoga_tab2_1380_init(struct device *dev)
{
int ret;
pr_info("detected Lenovo Yoga Tablet 2 Pro 1380F/L\n");
ret = lenovo_yoga_tab2_830_1050_init_codec();
if (ret)
return ret;
lenovo_yoga_tab2_830_1050_sys_off_handler =
register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1,
lenovo_yoga_tab2_830_1050_power_off, NULL);
if (IS_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler))
return PTR_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler);
return 0;
}
const struct x86_dev_info lenovo_yoga_tab2_1380_info __initconst = {
.i2c_client_info = lenovo_yoga_tab2_1380_i2c_clients,
.i2c_client_count = ARRAY_SIZE(lenovo_yoga_tab2_1380_i2c_clients),
.pdev_info = lenovo_yoga_tab2_1380_pdevs,
.pdev_count = ARRAY_SIZE(lenovo_yoga_tab2_1380_pdevs),
.gpio_button_swnodes = lenovo_yoga_tab2_830_1050_lid_swnodes,
.swnode_group = lenovo_yoga_tab2_830_1050_swnodes,
.modules = lenovo_yoga_tab2_modules,
.gpiochip_type = X86_GPIOCHIP_BAYTRAIL,
.init = lenovo_yoga_tab2_1380_init,
.exit = lenovo_yoga_tab2_830_1050_exit,
};
static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" };
static const char * const bq25890_1_psy[] = { "bq25890-charger-1" };
static const struct property_entry fg_bq25890_1_supply_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy),
{ }
};
static const struct software_node fg_bq25890_1_supply_node = {
.properties = fg_bq25890_1_supply_props,
};
static const struct property_entry lenovo_yt3_bq25892_0_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers),
PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40),
PROPERTY_ENTRY_BOOL("linux,skip-reset"),
PROPERTY_ENTRY_U32("ti,charge-current", 2048000),
PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000),
PROPERTY_ENTRY_U32("ti,termination-current", 128000),
PROPERTY_ENTRY_U32("ti,precharge-current", 128000),
PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000),
PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000),
PROPERTY_ENTRY_U32("ti,boost-max-current", 500000),
PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"),
{ }
};
static const struct software_node lenovo_yt3_bq25892_0_node = {
.properties = lenovo_yt3_bq25892_0_props,
};
static const struct property_entry lenovo_yt3_hideep_ts_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
PROPERTY_ENTRY_U32("touchscreen-size-y", 2560),
PROPERTY_ENTRY_U32("touchscreen-max-pressure", 255),
PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[0], 7, GPIO_ACTIVE_LOW),
{ }
};
static const struct software_node lenovo_yt3_hideep_ts_node = {
.properties = lenovo_yt3_hideep_ts_props,
};
static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
{
.board_info = {
.type = "bq27500",
.addr = 0x55,
.dev_name = "bq27500_0",
.swnode = &fg_bq25890_supply_node,
},
.adapter_path = "\\_SB_.PCI0.I2C1",
}, {
.board_info = {
.type = "bq25892",
.addr = 0x6b,
.dev_name = "bq25892_0",
.swnode = &lenovo_yt3_bq25892_0_node,
},
.adapter_path = "\\_SB_.PCI0.I2C1",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_GPIOINT,
.chip = "INT33FF:01",
.index = 5,
.trigger = ACPI_EDGE_SENSITIVE,
.polarity = ACPI_ACTIVE_LOW,
.con_id = "bq25892_0_irq",
},
}, {
.board_info = {
.type = "bq27500",
.addr = 0x55,
.dev_name = "bq27500_1",
.swnode = &fg_bq25890_1_supply_node,
},
.adapter_path = "\\_SB_.PCI0.I2C2",
}, {
.board_info = {
.type = "hideep_ts",
.addr = 0x6c,
.dev_name = "hideep_ts",
.swnode = &lenovo_yt3_hideep_ts_node,
},
.adapter_path = "\\_SB_.PCI0.I2C6",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_GPIOINT,
.chip = "INT33FF:03",
.index = 77,
.trigger = ACPI_LEVEL_SENSITIVE,
.polarity = ACPI_ACTIVE_LOW,
.con_id = "hideep_ts_irq",
},
}, {
.board_info = {
.type = "lp8557",
.addr = 0x2c,
.dev_name = "lp8557",
.platform_data = &lenovo_lp8557_reg_only_pdata,
},
.adapter_path = "\\_SB_.PCI0.I2C1",
}
};
static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
{ .max = 11, .key = KEY_PLAYPAUSE },
{ .max = 186, .key = KEY_VOICECOMMAND },
{ .max = 348, .key = KEY_VOLUMEUP },
{ .max = 752, .key = KEY_VOLUMEDOWN },
};
static struct arizona_micd_config lenovo_yt3_wm5102_micd_config[] = {
{ 0, 1, 0 },
{ ARIZONA_ACCDET_SRC, 2, 1 },
};
static struct arizona_pdata lenovo_yt3_wm5102_pdata = {
.irq_flags = IRQF_TRIGGER_LOW,
.micd_detect_debounce = 200,
.micd_ranges = arizona_micd_aosp_ranges,
.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges),
.hpdet_channel = ARIZONA_ACCDET_MODE_HPL,
.micd_bias_start_time = 1,
.micd_rate = 6,
.micd_configs = lenovo_yt3_wm5102_micd_config,
.num_micd_configs = ARRAY_SIZE(lenovo_yt3_wm5102_micd_config),
.micbias = {
[0] = {
.mV = 2800,
.ext_cap = 1,
.discharge = 1,
.soft_start = 0,
.bypass = 0,
},
[1] = {
.mV = 2800,
.ext_cap = 1,
.discharge = 1,
.soft_start = 0,
.bypass = 0,
},
[2] = {
.mV = 2800,
.ext_cap = 1,
.discharge = 1,
.soft_start = 0,
.bypass = 0,
},
},
};
static const struct property_entry lenovo_yt3_wm1502_props[] = {
PROPERTY_ENTRY_GPIO("wlf,spkvdd-ena-gpios",
&cherryview_gpiochip_nodes[0], 75, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("wlf,ldoena-gpios",
&cherryview_gpiochip_nodes[0], 81, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[0], 82, GPIO_ACTIVE_HIGH),
PROPERTY_ENTRY_GPIO("wlf,micd-pol-gpios", &arizona_gpiochip_node, 2, GPIO_ACTIVE_HIGH),
{ }
};
static const struct software_node lenovo_yt3_wm5102 = {
.properties = lenovo_yt3_wm1502_props,
.name = "wm5102",
};
static const struct software_node *lenovo_yt3_swnodes[] = {
&arizona_gpiochip_node,
&lenovo_yt3_wm5102,
NULL
};
static const struct x86_spi_dev_info lenovo_yt3_spi_devs[] __initconst = {
{
.board_info = {
.modalias = "wm5102",
.platform_data = &lenovo_yt3_wm5102_pdata,
.swnode = &lenovo_yt3_wm5102,
.max_speed_hz = 5000000,
},
.ctrl_path = "\\_SB_.PCI0.SPI1",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_GPIOINT,
.chip = "INT33FF:00",
.index = 91,
.trigger = ACPI_LEVEL_SENSITIVE,
.polarity = ACPI_ACTIVE_LOW,
.con_id = "wm5102_irq",
},
}
};
static int __init lenovo_yt3_init(struct device *dev)
{
int ret;
ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, "bq25892_0_ce",
true, GPIOD_OUT_HIGH, NULL);
if (ret < 0)
return ret;
ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, "bq25892_0_otg",
false, GPIOD_OUT_LOW, NULL);
if (ret < 0)
return ret;
intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
return 0;
}
static const char * const lenovo_yt3_modules[] __initconst = {
"spi_pxa2xx_platform",
NULL
};
const struct x86_dev_info lenovo_yt3_info __initconst = {
.i2c_client_info = lenovo_yt3_i2c_clients,
.i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients),
.spi_dev_info = lenovo_yt3_spi_devs,
.spi_dev_count = ARRAY_SIZE(lenovo_yt3_spi_devs),
.swnode_group = lenovo_yt3_swnodes,
.modules = lenovo_yt3_modules,
.gpiochip_type = X86_GPIOCHIP_CHERRYVIEW,
.init = lenovo_yt3_init,
};