diff -ru linux-3.13.0.orig/drivers/i2c/busses/i2c-designware-pcidrv.c linux-3.13.0/drivers/i2c/busses/i2c-designware-pcidrv.c --- linux-3.13.0.orig/drivers/i2c/busses/i2c-designware-pcidrv.c 2014-01-20 02:40:07.000000000 +0000 +++ linux-3.13.0/drivers/i2c/busses/i2c-designware-pcidrv.c 2014-07-16 03:06:14.000000000 +0000 @@ -54,6 +54,9 @@ medfield_3, medfield_4, medfield_5, + + haswell_0, + haswell_1, }; struct dw_pci_controller { @@ -132,6 +135,20 @@ .rx_fifo_depth = 32, .clk_khz = 25000, }, + [haswell_0] = { + .bus_num = -1, + .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD, + .tx_fifo_depth = 32, + .rx_fifo_depth = 32, + .clk_khz = 100000, + }, + [haswell_1] = { + .bus_num = -1, + .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD, + .tx_fifo_depth = 32, + .rx_fifo_depth = 32, + .clk_khz = 100000, + }, }; static struct i2c_algorithm i2c_dw_algo = { .master_xfer = i2c_dw_xfer, @@ -212,7 +229,7 @@ { struct dw_i2c_dev *dev; struct i2c_adapter *adap; - int r; + int r, adapter_num; struct dw_pci_controller *controller; if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) { @@ -270,8 +287,18 @@ adap->algo = &i2c_dw_algo; adap->dev.parent = &pdev->dev; adap->nr = controller->bus_num; + + switch (id->driver_data) { + case haswell_0: + case haswell_1: + adapter_num = id->driver_data - haswell_0; + break; + default: + adapter_num = adap->nr; + break; + } snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d", - adap->nr); + adapter_num); r = devm_request_irq(&pdev->dev, pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev); @@ -321,6 +348,9 @@ { PCI_VDEVICE(INTEL, 0x082C), medfield_0 }, { PCI_VDEVICE(INTEL, 0x082D), medfield_1 }, { PCI_VDEVICE(INTEL, 0x082E), medfield_2 }, + /* Haswell ULT */ + { PCI_VDEVICE(INTEL, 0x9c61), haswell_0 }, + { PCI_VDEVICE(INTEL, 0x9c62), haswell_1 }, { 0,} }; MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids); diff -ru linux-3.13.0.orig/drivers/platform/chrome/chromeos_laptop.c linux-3.13.0/drivers/platform/chrome/chromeos_laptop.c --- linux-3.13.0.orig/drivers/platform/chrome/chromeos_laptop.c 2014-01-20 02:40:07.000000000 +0000 +++ linux-3.13.0/drivers/platform/chrome/chromeos_laptop.c 2014-07-16 03:07:10.000000000 +0000 @@ -27,6 +27,7 @@ #include #include #include +#include #define ATMEL_TP_I2C_ADDR 0x4b #define ATMEL_TP_I2C_BL_ADDR 0x25 @@ -44,6 +45,8 @@ "SMBus I801 adapter", "i915 gmbus vga", "i915 gmbus panel", + "i2c-designware-pci-0", + "i2c-designware-pci-1", }; /* Keep this enum consistent with i2c_adapter_names */ @@ -51,22 +54,37 @@ I2C_ADAPTER_SMBUS = 0, I2C_ADAPTER_VGADDC, I2C_ADAPTER_PANEL, + I2C_ADAPTER_I2C0, + I2C_ADAPTER_I2C1, }; -static struct i2c_board_info __initdata cyapa_device = { +struct i2c_peripheral { + int (*add)(enum i2c_adapter_type type); + enum i2c_adapter_type type; +}; + +#define MAX_I2C_PERIPHERALS 3 + +struct chromeos_laptop { + struct i2c_peripheral i2c_peripherals[MAX_I2C_PERIPHERALS]; +}; + +static struct chromeos_laptop *cros_laptop; + +static struct i2c_board_info cyapa_device = { I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), .flags = I2C_CLIENT_WAKE, }; -static struct i2c_board_info __initdata isl_als_device = { +static struct i2c_board_info isl_als_device = { I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), }; -static struct i2c_board_info __initdata tsl2583_als_device = { +static struct i2c_board_info tsl2583_als_device = { I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), }; -static struct i2c_board_info __initdata tsl2563_als_device = { +static struct i2c_board_info tsl2563_als_device = { I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), }; @@ -89,7 +107,7 @@ .config_length = 0, }; -static struct i2c_board_info __initdata atmel_224s_tp_device = { +static struct i2c_board_info atmel_224s_tp_device = { I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR), .platform_data = &atmel_224s_tp_platform_data, .flags = I2C_CLIENT_WAKE, @@ -110,13 +128,13 @@ .config_length = 0, }; -static struct i2c_board_info __initdata atmel_1664s_device = { +static struct i2c_board_info atmel_1664s_device = { I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR), .platform_data = &atmel_1664s_platform_data, .flags = I2C_CLIENT_WAKE, }; -static struct i2c_client __init *__add_probed_i2c_device( +static struct i2c_client *__add_probed_i2c_device( const char *name, int bus, struct i2c_board_info *info, @@ -169,7 +187,7 @@ return client; } -static int __init __find_i2c_adap(struct device *dev, void *data) +static int __find_i2c_adap(struct device *dev, void *data) { const char *name = data; static const char *prefix = "i2c-"; @@ -180,7 +198,7 @@ return (strncmp(adapter->name, name, strlen(name)) == 0); } -static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +static int find_i2c_adapter_num(enum i2c_adapter_type type) { struct device *dev = NULL; struct i2c_adapter *adapter; @@ -189,8 +207,9 @@ dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, __find_i2c_adap); if (!dev) { - pr_err("%s: i2c adapter %s not found on system.\n", __func__, - name); + /* Adapters may appear later. Deferred probing will retry */ + pr_notice("%s: i2c adapter %s not found on system.\n", __func__, + name); return -ENODEV; } adapter = to_i2c_adapter(dev); @@ -205,7 +224,7 @@ * Returns NULL if no devices found. * See Documentation/i2c/instantiating-devices for more information. */ -static __init struct i2c_client *add_probed_i2c_device( +static struct i2c_client *add_probed_i2c_device( const char *name, enum i2c_adapter_type type, struct i2c_board_info *info, @@ -222,7 +241,7 @@ * info->addr. * Returns NULL if no device found. */ -static __init struct i2c_client *add_i2c_device(const char *name, +static struct i2c_client *add_i2c_device(const char *name, enum i2c_adapter_type type, struct i2c_board_info *info) { @@ -233,161 +252,289 @@ addr_list); } - -static struct i2c_client __init *add_smbus_device(const char *name, - struct i2c_board_info *info) +static int setup_cyapa_tp(enum i2c_adapter_type type) { - return add_i2c_device(name, I2C_ADAPTER_SMBUS, info); -} + if (tp) + return 0; -static int __init setup_cyapa_smbus_tp(const struct dmi_system_id *id) -{ - /* add cyapa touchpad on smbus */ - tp = add_smbus_device("trackpad", &cyapa_device); - return 0; + /* add cyapa touchpad */ + tp = add_i2c_device("trackpad", type, &cyapa_device); + return (!tp) ? -EAGAIN : 0; } -static int __init setup_atmel_224s_tp(const struct dmi_system_id *id) +static int setup_atmel_224s_tp(enum i2c_adapter_type type) { const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR, ATMEL_TP_I2C_ADDR, I2C_CLIENT_END }; + if (tp) + return 0; - /* add atmel mxt touchpad on VGA DDC GMBus */ - tp = add_probed_i2c_device("trackpad", I2C_ADAPTER_VGADDC, + /* add atmel mxt touchpad */ + tp = add_probed_i2c_device("trackpad", type, &atmel_224s_tp_device, addr_list); - return 0; + return (!tp) ? -EAGAIN : 0; } -static int __init setup_atmel_1664s_ts(const struct dmi_system_id *id) +static int setup_atmel_1664s_ts(enum i2c_adapter_type type) { const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR, ATMEL_TS_I2C_ADDR, I2C_CLIENT_END }; + if (ts) + return 0; - /* add atmel mxt touch device on PANEL GMBus */ - ts = add_probed_i2c_device("touchscreen", I2C_ADAPTER_PANEL, + /* add atmel mxt touch device */ + ts = add_probed_i2c_device("touchscreen", type, &atmel_1664s_device, addr_list); - return 0; + return (!ts) ? -EAGAIN : 0; } - -static int __init setup_isl29018_als(const struct dmi_system_id *id) +static int setup_isl29018_als(enum i2c_adapter_type type) { + if (als) + return 0; + /* add isl29018 light sensor */ - als = add_smbus_device("lightsensor", &isl_als_device); - return 0; + als = add_i2c_device("lightsensor", type, &isl_als_device); + return (!als) ? -EAGAIN : 0; } -static int __init setup_isl29023_als(const struct dmi_system_id *id) +static int setup_tsl2583_als(enum i2c_adapter_type type) { - /* add isl29023 light sensor on Panel GMBus */ - als = add_i2c_device("lightsensor", I2C_ADAPTER_PANEL, - &isl_als_device); - return 0; + if (als) + return 0; + + /* add tsl2583 light sensor */ + als = add_i2c_device(NULL, type, &tsl2583_als_device); + return (!als) ? -EAGAIN : 0; } -static int __init setup_tsl2583_als(const struct dmi_system_id *id) +static int setup_tsl2563_als(enum i2c_adapter_type type) { - /* add tsl2583 light sensor on smbus */ - als = add_smbus_device(NULL, &tsl2583_als_device); - return 0; + if (als) + return 0; + + /* add tsl2563 light sensor */ + als = add_i2c_device(NULL, type, &tsl2563_als_device); + return (!als) ? -EAGAIN : 0; } -static int __init setup_tsl2563_als(const struct dmi_system_id *id) +static int __init chromeos_laptop_dmi_matched(const struct dmi_system_id *id) { - /* add tsl2563 light sensor on smbus */ - als = add_smbus_device(NULL, &tsl2563_als_device); - return 0; + cros_laptop = (void *)id->driver_data; + pr_debug("DMI Matched %s.\n", id->ident); + + /* Indicate to dmi_scan that processing is done. */ + return 1; } -static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { +static int chromeos_laptop_probe(struct platform_device *pdev) +{ + int i; + int ret = 0; + + for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { + struct i2c_peripheral *i2c_dev; + + i2c_dev = &cros_laptop->i2c_peripherals[i]; + + /* No more peripherals. */ + if (i2c_dev->add == NULL) + break; + + /* Add the device. Set -EPROBE_DEFER on any failure */ + if (i2c_dev->add(i2c_dev->type)) + ret = -EPROBE_DEFER; + } + + return ret; +} + +static struct chromeos_laptop samsung_series_5_550 = { + .i2c_peripherals = { + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, + /* Light Sensor. */ + { .add = setup_isl29018_als, I2C_ADAPTER_SMBUS }, + }, +}; + +static struct chromeos_laptop samsung_series_5 = { + .i2c_peripherals = { + /* Light Sensor. */ + { .add = setup_tsl2583_als, I2C_ADAPTER_SMBUS }, + }, +}; + +static struct chromeos_laptop chromebook_pixel = { + .i2c_peripherals = { + /* Touch Screen. */ + { .add = setup_atmel_1664s_ts, I2C_ADAPTER_PANEL }, + /* Touchpad. */ + { .add = setup_atmel_224s_tp, I2C_ADAPTER_VGADDC }, + /* Light Sensor. */ + { .add = setup_isl29018_als, I2C_ADAPTER_PANEL }, + }, +}; + +static struct chromeos_laptop acer_c720 = { + .i2c_peripherals = { + /* Light Sensor. */ + { .add = setup_isl29018_als, I2C_ADAPTER_I2C1 }, + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_I2C0 }, + }, +}; + +static struct chromeos_laptop hp_chromebook_14 = { + .i2c_peripherals = { + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_I2C0 }, + }, +}; + +static struct chromeos_laptop acer_c7_chromebook = { + .i2c_peripherals = { + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, + }, +}; + +static struct chromeos_laptop acer_ac700 = { + .i2c_peripherals = { + /* Light Sensor. */ + { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS }, + }, +}; + +static struct chromeos_laptop hp_pavilion_14_chromebook = { + .i2c_peripherals = { + /* Touchpad. */ + { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, + }, +}; + +static struct chromeos_laptop cr48 = { + .i2c_peripherals = { + /* Light Sensor. */ + { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS }, + }, +}; + +#define _CBDD(board_) \ + .callback = chromeos_laptop_dmi_matched, \ + .driver_data = (void *)&board_ + +static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = { { - .ident = "Samsung Series 5 550 - Touchpad", + .ident = "Samsung Series 5 550", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"), }, - .callback = setup_cyapa_smbus_tp, + _CBDD(samsung_series_5_550), }, { - .ident = "Chromebook Pixel - Touchscreen", + .ident = "Samsung Series 5", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), - DMI_MATCH(DMI_PRODUCT_NAME, "Link"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alex"), }, - .callback = setup_atmel_1664s_ts, + _CBDD(samsung_series_5), }, { - .ident = "Chromebook Pixel - Touchpad", + .ident = "Chromebook Pixel", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), DMI_MATCH(DMI_PRODUCT_NAME, "Link"), }, - .callback = setup_atmel_224s_tp, + _CBDD(chromebook_pixel), }, { - .ident = "Samsung Series 5 550 - Light Sensor", + .ident = "Acer C720", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), - DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"), + DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"), }, - .callback = setup_isl29018_als, + _CBDD(acer_c720), }, { - .ident = "Chromebook Pixel - Light Sensor", + .ident = "HP Chromebook 14", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), - DMI_MATCH(DMI_PRODUCT_NAME, "Link"), + DMI_MATCH(DMI_PRODUCT_NAME, "Falco"), }, - .callback = setup_isl29023_als, + _CBDD(hp_chromebook_14), }, { - .ident = "Acer C7 Chromebook - Touchpad", + .ident = "Acer C7 Chromebook", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"), }, - .callback = setup_cyapa_smbus_tp, + _CBDD(acer_c7_chromebook), }, { - .ident = "HP Pavilion 14 Chromebook - Touchpad", + .ident = "Acer AC700", .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), }, - .callback = setup_cyapa_smbus_tp, + _CBDD(acer_ac700), }, { - .ident = "Samsung Series 5 - Light Sensor", + .ident = "HP Pavilion 14 Chromebook", .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "Alex"), + DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"), }, - .callback = setup_tsl2583_als, + _CBDD(hp_pavilion_14_chromebook), }, { - .ident = "Cr-48 - Light Sensor", + .ident = "Cr-48", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), }, - .callback = setup_tsl2563_als, - }, - { - .ident = "Acer AC700 - Light Sensor", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), - }, - .callback = setup_tsl2563_als, + _CBDD(cr48), }, { } }; MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table); +static struct platform_device *cros_platform_device; + +static struct platform_driver cros_platform_driver = { + .driver = { + .name = "chromeos_laptop", + .owner = THIS_MODULE, + }, + .probe = chromeos_laptop_probe, +}; + static int __init chromeos_laptop_init(void) { + int ret; if (!dmi_check_system(chromeos_laptop_dmi_table)) { pr_debug("%s unsupported system.\n", __func__); return -ENODEV; } + + ret = platform_driver_register(&cros_platform_driver); + if (ret) + return ret; + + cros_platform_device = platform_device_alloc("chromeos_laptop", -1); + if (!cros_platform_device) { + ret = -ENOMEM; + goto fail_platform_device1; + } + + ret = platform_device_add(cros_platform_device); + if (ret) + goto fail_platform_device2; + return 0; + +fail_platform_device2: + platform_device_put(cros_platform_device); +fail_platform_device1: + platform_driver_unregister(&cros_platform_driver); + return ret; } static void __exit chromeos_laptop_exit(void)