2013-10-21 03:58:47

by Benson Leung

[permalink] [raw]
Subject: [PATCH 0/6] Platform: x86: chromeos_laptop - Deferring and Haswell

The following patch series refactors the dmi check system and
returns -EPROBE_DEFER when an expected i2c adapter is not present
at probe time.

This will allow the touchpad, touchscreen, and light sensors on
Pixel to load even if the i915 DDC and PANEL buses are instantiated
after chromeos_laptop.

The deferred probing patches were sent previously, and have been cleaned up
slightly since.

Also one patch to clean up the placement of __initdata for the dmi_table.

Finally, add support for the Haswell generation Chromebook systems'
peripherals over the new native i2c-designware-pci busses.

The last three patches depend on this patch series :
https://lkml.org/lkml/2013/10/20/136

[PATCH 1/6] Platform: x86: chromeos_laptop - Restructure device associations
[PATCH 2/6] Platform: x86: chromeos_laptop - Use deferred probing
[PATCH 3/6] Platform: x86: chromeos_laptop - fix incorrect placement of __initdata tag
[PATCH 4/6] Platform: x86: chromeos_laptop - Add names of Haswell ULT i2c busses
[PATCH 5/6] Platform: x86: chromeos_laptop - Add HP Chromebook 14
[PATCH 6/6] Platform: x86: chromeos_laptop - Add Acer C720

Regards,
Benson


2013-10-21 03:58:56

by Benson Leung

[permalink] [raw]
Subject: [PATCH 4/6] Platform: x86: chromeos_laptop - Add names of Haswell ULT i2c busses

The designware-pci i2c busses will be named "i2c-designware-pci-0"
and "i2c-designware-pci-1" accordingly.

Signed-off-by: Benson Leung <[email protected]>
---
drivers/platform/x86/chromeos_laptop.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c
index 1c2747f..57ded03 100644
--- a/drivers/platform/x86/chromeos_laptop.c
+++ b/drivers/platform/x86/chromeos_laptop.c
@@ -45,6 +45,8 @@ const char *i2c_adapter_names[] = {
"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 */
@@ -52,6 +54,8 @@ enum i2c_adapter_type {
I2C_ADAPTER_SMBUS = 0,
I2C_ADAPTER_VGADDC,
I2C_ADAPTER_PANEL,
+ I2C_ADAPTER_I2C0,
+ I2C_ADAPTER_I2C1,
};

struct i2c_peripheral {
--
1.8.3.2

2013-10-21 03:59:00

by Benson Leung

[permalink] [raw]
Subject: [PATCH 6/6] Platform: x86: chromeos_laptop - Add Acer C720

Add the Acer C720 entries for trackpad and light sensor.

Signed-off-by: Benson Leung <[email protected]>
---
drivers/platform/x86/chromeos_laptop.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c
index a9ab335..6e2e7fd 100644
--- a/drivers/platform/x86/chromeos_laptop.c
+++ b/drivers/platform/x86/chromeos_laptop.c
@@ -385,6 +385,15 @@ static struct chromeos_laptop hp_chromebook_14 = {
},
};

+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 acer_c7_chromebook = {
.i2c_peripherals = {
/* Touchpad. */
@@ -449,6 +458,13 @@ static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = {
_CBDD(hp_chromebook_14),
},
{
+ .ident = "Acer C720",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
+ },
+ _CBDD(acer_c720),
+ },
+ {
.ident = "Acer C7 Chromebook",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"),
--
1.8.3.2

2013-10-21 03:59:32

by Benson Leung

[permalink] [raw]
Subject: [PATCH 5/6] Platform: x86: chromeos_laptop - Add HP Chromebook 14

Add support for the trackpad on HP Chromebook 14.

Signed-off-by: Benson Leung <[email protected]>
---
drivers/platform/x86/chromeos_laptop.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c
index 57ded03..a9ab335 100644
--- a/drivers/platform/x86/chromeos_laptop.c
+++ b/drivers/platform/x86/chromeos_laptop.c
@@ -378,6 +378,13 @@ static struct chromeos_laptop chromebook_pixel = {
},
};

+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. */
@@ -435,6 +442,13 @@ static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = {
_CBDD(chromebook_pixel),
},
{
+ .ident = "HP Chromebook 14",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "Falco"),
+ },
+ _CBDD(hp_chromebook_14),
+ },
+ {
.ident = "Acer C7 Chromebook",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"),
--
1.8.3.2

2013-10-21 03:58:55

by Benson Leung

[permalink] [raw]
Subject: [PATCH 3/6] Platform: x86: chromeos_laptop - fix incorrect placement of __initdata tag

__initdata tag should be placed between the variable name and equal
sign for the variable to be placed in the intended .init.data section.

Signed-off-by: Benson Leung <[email protected]>
---
drivers/platform/x86/chromeos_laptop.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c
index e542330..1c2747f 100644
--- a/drivers/platform/x86/chromeos_laptop.c
+++ b/drivers/platform/x86/chromeos_laptop.c
@@ -406,7 +406,7 @@ static struct chromeos_laptop cr48 = {
.callback = chromeos_laptop_dmi_matched, \
.driver_data = (void *)&board_

-static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = {
+static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = {
{
.ident = "Samsung Series 5 550",
.matches = {
--
1.8.3.2

2013-10-21 03:58:51

by Benson Leung

[permalink] [raw]
Subject: [PATCH 1/6] Platform: x86: chromeos_laptop - Restructure device associations

From: Aaron Durbin <[email protected]>

The previous code had a single DMI matching entry
for each device on a board. Instead provide a single
DMI entry for each board which references a structure
about each board that lists the associated peripherals.
This allows for a lower number of DMI matching sequences
as well making it easier to add new boards.

Signed-off-by: Aaron Durbin <[email protected]>
Signed-off-by: Benson Leung <[email protected]>
---
drivers/platform/x86/chromeos_laptop.c | 197 +++++++++++++++++++++------------
1 file changed, 126 insertions(+), 71 deletions(-)

diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c
index 3e5b4497..5c69cfd 100644
--- a/drivers/platform/x86/chromeos_laptop.c
+++ b/drivers/platform/x86/chromeos_laptop.c
@@ -53,6 +53,17 @@ enum i2c_adapter_type {
I2C_ADAPTER_PANEL,
};

+struct i2c_peripheral {
+ void (*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 i2c_board_info __initdata cyapa_device = {
I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
.flags = I2C_CLIENT_WAKE,
@@ -233,149 +244,193 @@ static __init struct i2c_client *add_i2c_device(const char *name,
addr_list);
}

-
-static struct i2c_client __init *add_smbus_device(const char *name,
- struct i2c_board_info *info)
-{
- return add_i2c_device(name, I2C_ADAPTER_SMBUS, info);
-}
-
-static int __init setup_cyapa_smbus_tp(const struct dmi_system_id *id)
+static int __init setup_cyapa_tp(enum i2c_adapter_type type)
{
- /* add cyapa touchpad on smbus */
- tp = add_smbus_device("trackpad", &cyapa_device);
+ /* add cyapa touchpad */
+ tp = add_i2c_device("trackpad", type, &cyapa_device);
return 0;
}

-static int __init setup_atmel_224s_tp(const struct dmi_system_id *id)
+static int __init 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 };

- /* 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;
}

-static int __init setup_atmel_1664s_ts(const struct dmi_system_id *id)
+static int __init 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 };

- /* 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;
}

-
-static int __init setup_isl29018_als(const struct dmi_system_id *id)
+static int __init setup_isl29018_als(enum i2c_adapter_type type)
{
/* add isl29018 light sensor */
- als = add_smbus_device("lightsensor", &isl_als_device);
+ als = add_i2c_device("lightsensor", type, &isl_als_device);
return 0;
}

-static int __init setup_isl29023_als(const struct dmi_system_id *id)
+static int __init 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);
+ /* add tsl2583 light sensor */
+ als = add_i2c_device(NULL, type, &tsl2583_als_device);
return 0;
}

-static int __init setup_tsl2583_als(const struct dmi_system_id *id)
+static int __init setup_tsl2563_als(enum i2c_adapter_type type)
{
- /* add tsl2583 light sensor on smbus */
- als = add_smbus_device(NULL, &tsl2583_als_device);
+ /* add tsl2563 light sensor */
+ als = add_i2c_device(NULL, type, &tsl2563_als_device);
return 0;
}

-static int __init setup_tsl2563_als(const struct dmi_system_id *id)
+static int __init
+chromeos_laptop_add_peripherals(const struct dmi_system_id *id)
{
- /* add tsl2563 light sensor on smbus */
- als = add_smbus_device(NULL, &tsl2563_als_device);
- return 0;
+ int i;
+ struct chromeos_laptop *cros_laptop = (void *)id->driver_data;
+
+ pr_debug("Adding peripherals for %s.\n", id->ident);
+
+ 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. */
+ i2c_dev->add(i2c_dev->type);
+ }
+
+ /* Indicate to dmi_scan that processing is done. */
+ return 1;
}

+static struct chromeos_laptop samsung_series_5_550 __initdata = {
+ .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 __initdata = {
+ .i2c_peripherals = {
+ /* Light Sensor. */
+ { .add = setup_tsl2583_als, I2C_ADAPTER_SMBUS },
+ },
+};
+
+static struct chromeos_laptop chromebook_pixel __initdata = {
+ .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_c7_chromebook __initdata = {
+ .i2c_peripherals = {
+ /* Touchpad. */
+ { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS },
+ },
+};
+
+static struct chromeos_laptop acer_ac700 __initdata = {
+ .i2c_peripherals = {
+ /* Light Sensor. */
+ { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS },
+ },
+};
+
+static struct chromeos_laptop hp_pavilion_14_chromebook __initdata = {
+ .i2c_peripherals = {
+ /* Touchpad. */
+ { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS },
+ },
+};
+
+static struct chromeos_laptop cr48 __initdata = {
+ .i2c_peripherals = {
+ /* Light Sensor. */
+ { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS },
+ },
+};
+
+#define _CBDD(board_) \
+ .callback = &chromeos_laptop_add_peripherals, \
+ .driver_data = (void *)&board_
+
static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = {
{
- .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,
- },
- {
- .ident = "Chromebook Pixel - Touchscreen",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
- },
- .callback = setup_atmel_1664s_ts,
- },
- {
- .ident = "Chromebook Pixel - Touchpad",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
- },
- .callback = setup_atmel_224s_tp,
+ _CBDD(samsung_series_5_550),
},
{
- .ident = "Samsung Series 5 550 - Light Sensor",
+ .ident = "Samsung Series 5",
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alex"),
},
- .callback = setup_isl29018_als,
+ _CBDD(samsung_series_5),
},
{
- .ident = "Chromebook Pixel - Light Sensor",
+ .ident = "Chromebook Pixel",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
},
- .callback = setup_isl29023_als,
+ _CBDD(chromebook_pixel),
},
{
- .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),
},
{ }
};
--
1.8.3.2

2013-10-21 04:00:12

by Benson Leung

[permalink] [raw]
Subject: [PATCH 2/6] Platform: x86: chromeos_laptop - Use deferred probing

Further refactor chromeos_laptop, adding a probe function.
Init will call dmi_check_system, but will only use the match to select
a chromeos_laptop structure of the current board.

Probe will add the devices, and on errors return -EPROBE_DEFER.
If i2c adapters are loaded after chromeos_laptop inits, the deferred
probe will instantiate the peripherals when the bus appears.

Signed-off-by: Benson Leung <[email protected]>
Reviewed-by: Aaron Durbin <[email protected]>
---
drivers/platform/x86/chromeos_laptop.c | 144 +++++++++++++++++++++++----------
1 file changed, 101 insertions(+), 43 deletions(-)

diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c
index 5c69cfd..e542330 100644
--- a/drivers/platform/x86/chromeos_laptop.c
+++ b/drivers/platform/x86/chromeos_laptop.c
@@ -27,6 +27,7 @@
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/platform_device.h>

#define ATMEL_TP_I2C_ADDR 0x4b
#define ATMEL_TP_I2C_BL_ADDR 0x25
@@ -54,7 +55,7 @@ enum i2c_adapter_type {
};

struct i2c_peripheral {
- void (*add)(enum i2c_adapter_type type);
+ int (*add)(enum i2c_adapter_type type);
enum i2c_adapter_type type;
};

@@ -64,20 +65,22 @@ struct chromeos_laptop {
struct i2c_peripheral i2c_peripherals[MAX_I2C_PERIPHERALS];
};

-static struct i2c_board_info __initdata cyapa_device = {
+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),
};

@@ -100,7 +103,7 @@ static struct mxt_platform_data atmel_224s_tp_platform_data = {
.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,
@@ -121,13 +124,13 @@ static struct mxt_platform_data atmel_1664s_platform_data = {
.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,
@@ -180,7 +183,7 @@ static struct i2c_client __init *__add_probed_i2c_device(
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-";
@@ -191,7 +194,7 @@ static int __init __find_i2c_adap(struct device *dev, void *data)
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;
@@ -200,8 +203,9 @@ static int __init find_i2c_adapter_num(enum i2c_adapter_type type)
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);
@@ -216,7 +220,7 @@ static int __init find_i2c_adapter_num(enum i2c_adapter_type type)
* 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,
@@ -233,7 +237,7 @@ static __init struct i2c_client *add_probed_i2c_device(
* 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)
{
@@ -244,65 +248,87 @@ static __init struct i2c_client *add_i2c_device(const char *name,
addr_list);
}

-static int __init setup_cyapa_tp(enum i2c_adapter_type type)
+static int setup_cyapa_tp(enum i2c_adapter_type type)
{
+ if (tp)
+ return 0;
+
/* add cyapa touchpad */
tp = add_i2c_device("trackpad", type, &cyapa_device);
- return 0;
+ return (!tp) ? -EAGAIN : 0;
}

-static int __init setup_atmel_224s_tp(enum i2c_adapter_type type)
+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 */
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(enum i2c_adapter_type type)
+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 */
ts = add_probed_i2c_device("touchscreen", type,
&atmel_1664s_device, addr_list);
- return 0;
+ return (!ts) ? -EAGAIN : 0;
}

-static int __init setup_isl29018_als(enum i2c_adapter_type type)
+static int setup_isl29018_als(enum i2c_adapter_type type)
{
+ if (als)
+ return 0;
+
/* add isl29018 light sensor */
als = add_i2c_device("lightsensor", type, &isl_als_device);
- return 0;
+ return (!als) ? -EAGAIN : 0;
}

-static int __init setup_tsl2583_als(enum i2c_adapter_type type)
+static int setup_tsl2583_als(enum i2c_adapter_type type)
{
+ if (als)
+ return 0;
+
/* add tsl2583 light sensor */
als = add_i2c_device(NULL, type, &tsl2583_als_device);
- return 0;
+ return (!als) ? -EAGAIN : 0;
}

-static int __init setup_tsl2563_als(enum i2c_adapter_type type)
+static int setup_tsl2563_als(enum i2c_adapter_type type)
{
+ if (als)
+ return 0;
+
/* add tsl2563 light sensor */
als = add_i2c_device(NULL, type, &tsl2563_als_device);
- return 0;
+ return (!als) ? -EAGAIN : 0;
}

-static int __init
-chromeos_laptop_add_peripherals(const struct dmi_system_id *id)
+static int __init chromeos_laptop_dmi_matched(const struct dmi_system_id *id)
{
- int i;
- struct chromeos_laptop *cros_laptop = (void *)id->driver_data;
+ cros_laptop = (void *)id->driver_data;
+ pr_debug("DMI Matched %s.\n", id->ident);

- pr_debug("Adding peripherals for %s.\n", id->ident);
+ /* Indicate to dmi_scan that processing is done. */
+ return 1;
+}
+
+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;
@@ -313,15 +339,15 @@ chromeos_laptop_add_peripherals(const struct dmi_system_id *id)
if (i2c_dev->add == NULL)
break;

- /* Add the device. */
- i2c_dev->add(i2c_dev->type);
+ /* Add the device. Set -EPROBE_DEFER on any failure */
+ if (i2c_dev->add(i2c_dev->type))
+ ret = -EPROBE_DEFER;
}

- /* Indicate to dmi_scan that processing is done. */
- return 1;
+ return ret;
}

-static struct chromeos_laptop samsung_series_5_550 __initdata = {
+static struct chromeos_laptop samsung_series_5_550 = {
.i2c_peripherals = {
/* Touchpad. */
{ .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS },
@@ -330,14 +356,14 @@ static struct chromeos_laptop samsung_series_5_550 __initdata = {
},
};

-static struct chromeos_laptop samsung_series_5 __initdata = {
+static struct chromeos_laptop samsung_series_5 = {
.i2c_peripherals = {
/* Light Sensor. */
{ .add = setup_tsl2583_als, I2C_ADAPTER_SMBUS },
},
};

-static struct chromeos_laptop chromebook_pixel __initdata = {
+static struct chromeos_laptop chromebook_pixel = {
.i2c_peripherals = {
/* Touch Screen. */
{ .add = setup_atmel_1664s_ts, I2C_ADAPTER_PANEL },
@@ -348,28 +374,28 @@ static struct chromeos_laptop chromebook_pixel __initdata = {
},
};

-static struct chromeos_laptop acer_c7_chromebook __initdata = {
+static struct chromeos_laptop acer_c7_chromebook = {
.i2c_peripherals = {
/* Touchpad. */
{ .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS },
},
};

-static struct chromeos_laptop acer_ac700 __initdata = {
+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 __initdata = {
+static struct chromeos_laptop hp_pavilion_14_chromebook = {
.i2c_peripherals = {
/* Touchpad. */
{ .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS },
},
};

-static struct chromeos_laptop cr48 __initdata = {
+static struct chromeos_laptop cr48 = {
.i2c_peripherals = {
/* Light Sensor. */
{ .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS },
@@ -377,7 +403,7 @@ static struct chromeos_laptop cr48 __initdata = {
};

#define _CBDD(board_) \
- .callback = &chromeos_laptop_add_peripherals, \
+ .callback = chromeos_laptop_dmi_matched, \
.driver_data = (void *)&board_

static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = {
@@ -436,13 +462,45 @@ static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = {
};
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)
--
1.8.3.2