aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-29 23:06:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-29 23:06:01 -0500
commite9e352e9100b98aed1a5fb9e33355c29fb07d5b1 (patch)
tree92eb59640f3bfc33f55c54f0494052530a9560dd /drivers/platform
parentb3a4bcaa5a56860610bd096829702f80273b5a67 (diff)
parent2b8454a75b90d7cd1ac325a0baba77244733354f (diff)
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/olof/chrome-platform
Pull chrome platform cleanups and improvements from Olof Johansson: - Use deferred probing on Chrome OS platforms for the i2c device registration. This fixes a long-standing race of initialization of touchpad/screen on Chromebooks. - Added in platform device registration for pstore console on supported hardware - Misc smaller fixes (__initdata, module exit cleanup, etc) * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/olof/chrome-platform: platform/chrome: unregister platform driver/device when module exit platform/chrome: Make i2c_adapter_names static platform/chrome: chromeos_laptop - fix incorrect placement of __initdata tag platform/chrome: chromeos_laptop - Use deferred probing platform/chrome: chromeos_laptop - Restructure device associations platform/chrome: Add pstore platform_device
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/chrome/Kconfig14
-rw-r--r--drivers/platform/chrome/Makefile1
-rw-r--r--drivers/platform/chrome/chromeos_laptop.c298
-rw-r--r--drivers/platform/chrome/chromeos_pstore.c101
4 files changed, 323 insertions, 91 deletions
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index b13303e75a34..440ed776efd4 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -25,4 +25,18 @@ config CHROMEOS_LAPTOP
25 If you have a supported Chromebook, choose Y or M here. 25 If you have a supported Chromebook, choose Y or M here.
26 The module will be called chromeos_laptop. 26 The module will be called chromeos_laptop.
27 27
28config CHROMEOS_PSTORE
29 tristate "Chrome OS pstore support"
30 ---help---
31 This module instantiates the persistent storage on x86 ChromeOS
32 devices. It can be used to store away console logs and crash
33 information across reboots.
34
35 The range of memory used is 0xf00000-0x1000000, traditionally
36 the memory used to back VGA controller memory.
37
38 If you have a supported Chromebook, choose Y or M here.
39 The module will be called chromeos_pstore.
40
41
28endif # CHROMEOS_PLATFORMS 42endif # CHROMEOS_PLATFORMS
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 015e9195e226..2b860ca7450f 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -1,2 +1,3 @@
1 1
2obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o 2obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
3obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c
index 3e5b4497a1d0..7f3aad0e115c 100644
--- a/drivers/platform/chrome/chromeos_laptop.c
+++ b/drivers/platform/chrome/chromeos_laptop.c
@@ -27,6 +27,7 @@
27#include <linux/input.h> 27#include <linux/input.h>
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/platform_device.h>
30 31
31#define ATMEL_TP_I2C_ADDR 0x4b 32#define ATMEL_TP_I2C_ADDR 0x4b
32#define ATMEL_TP_I2C_BL_ADDR 0x25 33#define ATMEL_TP_I2C_BL_ADDR 0x25
@@ -40,7 +41,7 @@ static struct i2c_client *als;
40static struct i2c_client *tp; 41static struct i2c_client *tp;
41static struct i2c_client *ts; 42static struct i2c_client *ts;
42 43
43const char *i2c_adapter_names[] = { 44static const char *i2c_adapter_names[] = {
44 "SMBus I801 adapter", 45 "SMBus I801 adapter",
45 "i915 gmbus vga", 46 "i915 gmbus vga",
46 "i915 gmbus panel", 47 "i915 gmbus panel",
@@ -53,20 +54,33 @@ enum i2c_adapter_type {
53 I2C_ADAPTER_PANEL, 54 I2C_ADAPTER_PANEL,
54}; 55};
55 56
56static struct i2c_board_info __initdata cyapa_device = { 57struct i2c_peripheral {
58 int (*add)(enum i2c_adapter_type type);
59 enum i2c_adapter_type type;
60};
61
62#define MAX_I2C_PERIPHERALS 3
63
64struct chromeos_laptop {
65 struct i2c_peripheral i2c_peripherals[MAX_I2C_PERIPHERALS];
66};
67
68static struct chromeos_laptop *cros_laptop;
69
70static struct i2c_board_info cyapa_device = {
57 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), 71 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
58 .flags = I2C_CLIENT_WAKE, 72 .flags = I2C_CLIENT_WAKE,
59}; 73};
60 74
61static struct i2c_board_info __initdata isl_als_device = { 75static struct i2c_board_info isl_als_device = {
62 I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), 76 I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
63}; 77};
64 78
65static struct i2c_board_info __initdata tsl2583_als_device = { 79static struct i2c_board_info tsl2583_als_device = {
66 I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), 80 I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR),
67}; 81};
68 82
69static struct i2c_board_info __initdata tsl2563_als_device = { 83static struct i2c_board_info tsl2563_als_device = {
70 I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), 84 I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR),
71}; 85};
72 86
@@ -89,7 +103,7 @@ static struct mxt_platform_data atmel_224s_tp_platform_data = {
89 .config_length = 0, 103 .config_length = 0,
90}; 104};
91 105
92static struct i2c_board_info __initdata atmel_224s_tp_device = { 106static struct i2c_board_info atmel_224s_tp_device = {
93 I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR), 107 I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR),
94 .platform_data = &atmel_224s_tp_platform_data, 108 .platform_data = &atmel_224s_tp_platform_data,
95 .flags = I2C_CLIENT_WAKE, 109 .flags = I2C_CLIENT_WAKE,
@@ -110,13 +124,13 @@ static struct mxt_platform_data atmel_1664s_platform_data = {
110 .config_length = 0, 124 .config_length = 0,
111}; 125};
112 126
113static struct i2c_board_info __initdata atmel_1664s_device = { 127static struct i2c_board_info atmel_1664s_device = {
114 I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR), 128 I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR),
115 .platform_data = &atmel_1664s_platform_data, 129 .platform_data = &atmel_1664s_platform_data,
116 .flags = I2C_CLIENT_WAKE, 130 .flags = I2C_CLIENT_WAKE,
117}; 131};
118 132
119static struct i2c_client __init *__add_probed_i2c_device( 133static struct i2c_client *__add_probed_i2c_device(
120 const char *name, 134 const char *name,
121 int bus, 135 int bus,
122 struct i2c_board_info *info, 136 struct i2c_board_info *info,
@@ -169,7 +183,7 @@ static struct i2c_client __init *__add_probed_i2c_device(
169 return client; 183 return client;
170} 184}
171 185
172static int __init __find_i2c_adap(struct device *dev, void *data) 186static int __find_i2c_adap(struct device *dev, void *data)
173{ 187{
174 const char *name = data; 188 const char *name = data;
175 static const char *prefix = "i2c-"; 189 static const char *prefix = "i2c-";
@@ -180,7 +194,7 @@ static int __init __find_i2c_adap(struct device *dev, void *data)
180 return (strncmp(adapter->name, name, strlen(name)) == 0); 194 return (strncmp(adapter->name, name, strlen(name)) == 0);
181} 195}
182 196
183static int __init find_i2c_adapter_num(enum i2c_adapter_type type) 197static int find_i2c_adapter_num(enum i2c_adapter_type type)
184{ 198{
185 struct device *dev = NULL; 199 struct device *dev = NULL;
186 struct i2c_adapter *adapter; 200 struct i2c_adapter *adapter;
@@ -189,8 +203,9 @@ static int __init find_i2c_adapter_num(enum i2c_adapter_type type)
189 dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, 203 dev = bus_find_device(&i2c_bus_type, NULL, (void *)name,
190 __find_i2c_adap); 204 __find_i2c_adap);
191 if (!dev) { 205 if (!dev) {
192 pr_err("%s: i2c adapter %s not found on system.\n", __func__, 206 /* Adapters may appear later. Deferred probing will retry */
193 name); 207 pr_notice("%s: i2c adapter %s not found on system.\n", __func__,
208 name);
194 return -ENODEV; 209 return -ENODEV;
195 } 210 }
196 adapter = to_i2c_adapter(dev); 211 adapter = to_i2c_adapter(dev);
@@ -205,7 +220,7 @@ static int __init find_i2c_adapter_num(enum i2c_adapter_type type)
205 * Returns NULL if no devices found. 220 * Returns NULL if no devices found.
206 * See Documentation/i2c/instantiating-devices for more information. 221 * See Documentation/i2c/instantiating-devices for more information.
207 */ 222 */
208static __init struct i2c_client *add_probed_i2c_device( 223static struct i2c_client *add_probed_i2c_device(
209 const char *name, 224 const char *name,
210 enum i2c_adapter_type type, 225 enum i2c_adapter_type type,
211 struct i2c_board_info *info, 226 struct i2c_board_info *info,
@@ -222,7 +237,7 @@ static __init struct i2c_client *add_probed_i2c_device(
222 * info->addr. 237 * info->addr.
223 * Returns NULL if no device found. 238 * Returns NULL if no device found.
224 */ 239 */
225static __init struct i2c_client *add_i2c_device(const char *name, 240static struct i2c_client *add_i2c_device(const char *name,
226 enum i2c_adapter_type type, 241 enum i2c_adapter_type type,
227 struct i2c_board_info *info) 242 struct i2c_board_info *info)
228{ 243{
@@ -233,161 +248,259 @@ static __init struct i2c_client *add_i2c_device(const char *name,
233 addr_list); 248 addr_list);
234} 249}
235 250
236 251static int setup_cyapa_tp(enum i2c_adapter_type type)
237static struct i2c_client __init *add_smbus_device(const char *name,
238 struct i2c_board_info *info)
239{ 252{
240 return add_i2c_device(name, I2C_ADAPTER_SMBUS, info); 253 if (tp)
241} 254 return 0;
242 255
243static int __init setup_cyapa_smbus_tp(const struct dmi_system_id *id) 256 /* add cyapa touchpad */
244{ 257 tp = add_i2c_device("trackpad", type, &cyapa_device);
245 /* add cyapa touchpad on smbus */ 258 return (!tp) ? -EAGAIN : 0;
246 tp = add_smbus_device("trackpad", &cyapa_device);
247 return 0;
248} 259}
249 260
250static int __init setup_atmel_224s_tp(const struct dmi_system_id *id) 261static int setup_atmel_224s_tp(enum i2c_adapter_type type)
251{ 262{
252 const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR, 263 const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR,
253 ATMEL_TP_I2C_ADDR, 264 ATMEL_TP_I2C_ADDR,
254 I2C_CLIENT_END }; 265 I2C_CLIENT_END };
266 if (tp)
267 return 0;
255 268
256 /* add atmel mxt touchpad on VGA DDC GMBus */ 269 /* add atmel mxt touchpad */
257 tp = add_probed_i2c_device("trackpad", I2C_ADAPTER_VGADDC, 270 tp = add_probed_i2c_device("trackpad", type,
258 &atmel_224s_tp_device, addr_list); 271 &atmel_224s_tp_device, addr_list);
259 return 0; 272 return (!tp) ? -EAGAIN : 0;
260} 273}
261 274
262static int __init setup_atmel_1664s_ts(const struct dmi_system_id *id) 275static int setup_atmel_1664s_ts(enum i2c_adapter_type type)
263{ 276{
264 const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR, 277 const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR,
265 ATMEL_TS_I2C_ADDR, 278 ATMEL_TS_I2C_ADDR,
266 I2C_CLIENT_END }; 279 I2C_CLIENT_END };
280 if (ts)
281 return 0;
267 282
268 /* add atmel mxt touch device on PANEL GMBus */ 283 /* add atmel mxt touch device */
269 ts = add_probed_i2c_device("touchscreen", I2C_ADAPTER_PANEL, 284 ts = add_probed_i2c_device("touchscreen", type,
270 &atmel_1664s_device, addr_list); 285 &atmel_1664s_device, addr_list);
271 return 0; 286 return (!ts) ? -EAGAIN : 0;
272} 287}
273 288
274 289static int setup_isl29018_als(enum i2c_adapter_type type)
275static int __init setup_isl29018_als(const struct dmi_system_id *id)
276{ 290{
291 if (als)
292 return 0;
293
277 /* add isl29018 light sensor */ 294 /* add isl29018 light sensor */
278 als = add_smbus_device("lightsensor", &isl_als_device); 295 als = add_i2c_device("lightsensor", type, &isl_als_device);
279 return 0; 296 return (!als) ? -EAGAIN : 0;
280} 297}
281 298
282static int __init setup_isl29023_als(const struct dmi_system_id *id) 299static int setup_tsl2583_als(enum i2c_adapter_type type)
283{ 300{
284 /* add isl29023 light sensor on Panel GMBus */ 301 if (als)
285 als = add_i2c_device("lightsensor", I2C_ADAPTER_PANEL, 302 return 0;
286 &isl_als_device); 303
287 return 0; 304 /* add tsl2583 light sensor */
305 als = add_i2c_device(NULL, type, &tsl2583_als_device);
306 return (!als) ? -EAGAIN : 0;
288} 307}
289 308
290static int __init setup_tsl2583_als(const struct dmi_system_id *id) 309static int setup_tsl2563_als(enum i2c_adapter_type type)
291{ 310{
292 /* add tsl2583 light sensor on smbus */ 311 if (als)
293 als = add_smbus_device(NULL, &tsl2583_als_device); 312 return 0;
294 return 0; 313
314 /* add tsl2563 light sensor */
315 als = add_i2c_device(NULL, type, &tsl2563_als_device);
316 return (!als) ? -EAGAIN : 0;
295} 317}
296 318
297static int __init setup_tsl2563_als(const struct dmi_system_id *id) 319static int __init chromeos_laptop_dmi_matched(const struct dmi_system_id *id)
298{ 320{
299 /* add tsl2563 light sensor on smbus */ 321 cros_laptop = (void *)id->driver_data;
300 als = add_smbus_device(NULL, &tsl2563_als_device); 322 pr_debug("DMI Matched %s.\n", id->ident);
301 return 0; 323
324 /* Indicate to dmi_scan that processing is done. */
325 return 1;
302} 326}
303 327
304static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { 328static int chromeos_laptop_probe(struct platform_device *pdev)
305 { 329{
306 .ident = "Samsung Series 5 550 - Touchpad", 330 int i;
307 .matches = { 331 int ret = 0;
308 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), 332
309 DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"), 333 for (i = 0; i < MAX_I2C_PERIPHERALS; i++) {
310 }, 334 struct i2c_peripheral *i2c_dev;
311 .callback = setup_cyapa_smbus_tp, 335
336 i2c_dev = &cros_laptop->i2c_peripherals[i];
337
338 /* No more peripherals. */
339 if (i2c_dev->add == NULL)
340 break;
341
342 /* Add the device. Set -EPROBE_DEFER on any failure */
343 if (i2c_dev->add(i2c_dev->type))
344 ret = -EPROBE_DEFER;
345 }
346
347 return ret;
348}
349
350static struct chromeos_laptop samsung_series_5_550 = {
351 .i2c_peripherals = {
352 /* Touchpad. */
353 { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS },
354 /* Light Sensor. */
355 { .add = setup_isl29018_als, I2C_ADAPTER_SMBUS },
312 }, 356 },
313 { 357};
314 .ident = "Chromebook Pixel - Touchscreen", 358
315 .matches = { 359static struct chromeos_laptop samsung_series_5 = {
316 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), 360 .i2c_peripherals = {
317 DMI_MATCH(DMI_PRODUCT_NAME, "Link"), 361 /* Light Sensor. */
318 }, 362 { .add = setup_tsl2583_als, I2C_ADAPTER_SMBUS },
319 .callback = setup_atmel_1664s_ts, 363 },
364};
365
366static struct chromeos_laptop chromebook_pixel = {
367 .i2c_peripherals = {
368 /* Touch Screen. */
369 { .add = setup_atmel_1664s_ts, I2C_ADAPTER_PANEL },
370 /* Touchpad. */
371 { .add = setup_atmel_224s_tp, I2C_ADAPTER_VGADDC },
372 /* Light Sensor. */
373 { .add = setup_isl29018_als, I2C_ADAPTER_PANEL },
374 },
375};
376
377static struct chromeos_laptop acer_c7_chromebook = {
378 .i2c_peripherals = {
379 /* Touchpad. */
380 { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS },
381 },
382};
383
384static struct chromeos_laptop acer_ac700 = {
385 .i2c_peripherals = {
386 /* Light Sensor. */
387 { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS },
320 }, 388 },
389};
390
391static struct chromeos_laptop hp_pavilion_14_chromebook = {
392 .i2c_peripherals = {
393 /* Touchpad. */
394 { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS },
395 },
396};
397
398static struct chromeos_laptop cr48 = {
399 .i2c_peripherals = {
400 /* Light Sensor. */
401 { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS },
402 },
403};
404
405#define _CBDD(board_) \
406 .callback = chromeos_laptop_dmi_matched, \
407 .driver_data = (void *)&board_
408
409static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = {
321 { 410 {
322 .ident = "Chromebook Pixel - Touchpad", 411 .ident = "Samsung Series 5 550",
323 .matches = { 412 .matches = {
324 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), 413 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
325 DMI_MATCH(DMI_PRODUCT_NAME, "Link"), 414 DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"),
326 }, 415 },
327 .callback = setup_atmel_224s_tp, 416 _CBDD(samsung_series_5_550),
328 }, 417 },
329 { 418 {
330 .ident = "Samsung Series 5 550 - Light Sensor", 419 .ident = "Samsung Series 5",
331 .matches = { 420 .matches = {
332 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), 421 DMI_MATCH(DMI_PRODUCT_NAME, "Alex"),
333 DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"),
334 }, 422 },
335 .callback = setup_isl29018_als, 423 _CBDD(samsung_series_5),
336 }, 424 },
337 { 425 {
338 .ident = "Chromebook Pixel - Light Sensor", 426 .ident = "Chromebook Pixel",
339 .matches = { 427 .matches = {
340 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), 428 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
341 DMI_MATCH(DMI_PRODUCT_NAME, "Link"), 429 DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
342 }, 430 },
343 .callback = setup_isl29023_als, 431 _CBDD(chromebook_pixel),
344 }, 432 },
345 { 433 {
346 .ident = "Acer C7 Chromebook - Touchpad", 434 .ident = "Acer C7 Chromebook",
347 .matches = { 435 .matches = {
348 DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"), 436 DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"),
349 }, 437 },
350 .callback = setup_cyapa_smbus_tp, 438 _CBDD(acer_c7_chromebook),
351 }, 439 },
352 { 440 {
353 .ident = "HP Pavilion 14 Chromebook - Touchpad", 441 .ident = "Acer AC700",
354 .matches = { 442 .matches = {
355 DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"), 443 DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
356 }, 444 },
357 .callback = setup_cyapa_smbus_tp, 445 _CBDD(acer_ac700),
358 }, 446 },
359 { 447 {
360 .ident = "Samsung Series 5 - Light Sensor", 448 .ident = "HP Pavilion 14 Chromebook",
361 .matches = { 449 .matches = {
362 DMI_MATCH(DMI_PRODUCT_NAME, "Alex"), 450 DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"),
363 }, 451 },
364 .callback = setup_tsl2583_als, 452 _CBDD(hp_pavilion_14_chromebook),
365 }, 453 },
366 { 454 {
367 .ident = "Cr-48 - Light Sensor", 455 .ident = "Cr-48",
368 .matches = { 456 .matches = {
369 DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), 457 DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
370 }, 458 },
371 .callback = setup_tsl2563_als, 459 _CBDD(cr48),
372 },
373 {
374 .ident = "Acer AC700 - Light Sensor",
375 .matches = {
376 DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
377 },
378 .callback = setup_tsl2563_als,
379 }, 460 },
380 { } 461 { }
381}; 462};
382MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table); 463MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table);
383 464
465static struct platform_device *cros_platform_device;
466
467static struct platform_driver cros_platform_driver = {
468 .driver = {
469 .name = "chromeos_laptop",
470 .owner = THIS_MODULE,
471 },
472 .probe = chromeos_laptop_probe,
473};
474
384static int __init chromeos_laptop_init(void) 475static int __init chromeos_laptop_init(void)
385{ 476{
477 int ret;
386 if (!dmi_check_system(chromeos_laptop_dmi_table)) { 478 if (!dmi_check_system(chromeos_laptop_dmi_table)) {
387 pr_debug("%s unsupported system.\n", __func__); 479 pr_debug("%s unsupported system.\n", __func__);
388 return -ENODEV; 480 return -ENODEV;
389 } 481 }
482
483 ret = platform_driver_register(&cros_platform_driver);
484 if (ret)
485 return ret;
486
487 cros_platform_device = platform_device_alloc("chromeos_laptop", -1);
488 if (!cros_platform_device) {
489 ret = -ENOMEM;
490 goto fail_platform_device1;
491 }
492
493 ret = platform_device_add(cros_platform_device);
494 if (ret)
495 goto fail_platform_device2;
496
390 return 0; 497 return 0;
498
499fail_platform_device2:
500 platform_device_put(cros_platform_device);
501fail_platform_device1:
502 platform_driver_unregister(&cros_platform_driver);
503 return ret;
391} 504}
392 505
393static void __exit chromeos_laptop_exit(void) 506static void __exit chromeos_laptop_exit(void)
@@ -398,6 +511,9 @@ static void __exit chromeos_laptop_exit(void)
398 i2c_unregister_device(tp); 511 i2c_unregister_device(tp);
399 if (ts) 512 if (ts)
400 i2c_unregister_device(ts); 513 i2c_unregister_device(ts);
514
515 platform_device_unregister(cros_platform_device);
516 platform_driver_unregister(&cros_platform_driver);
401} 517}
402 518
403module_init(chromeos_laptop_init); 519module_init(chromeos_laptop_init);
diff --git a/drivers/platform/chrome/chromeos_pstore.c b/drivers/platform/chrome/chromeos_pstore.c
new file mode 100644
index 000000000000..e0e0e65cf442
--- /dev/null
+++ b/drivers/platform/chrome/chromeos_pstore.c
@@ -0,0 +1,101 @@
1/*
2 * chromeos_pstore.c - Driver to instantiate Chromebook ramoops device
3 *
4 * Copyright (C) 2013 Google, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 of the License.
9 */
10
11#include <linux/dmi.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/pstore_ram.h>
15
16static struct dmi_system_id chromeos_pstore_dmi_table[] __initdata = {
17 {
18 /*
19 * Today all Chromebooks/boxes ship with GOOGLE as vendor and
20 * coreboot as bios vendor. No other systems with this
21 * combination are known to date.
22 */
23 .matches = {
24 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
25 DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
26 },
27 },
28 {
29 /*
30 * The first Samsung Chromebox and Chromebook Series 5 550 use
31 * coreboot but with Samsung as the system vendor.
32 */
33 .matches = {
34 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
35 DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
36 },
37 },
38 {
39 /* x86-alex, the first Samsung Chromebook. */
40 .matches = {
41 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
42 DMI_MATCH(DMI_PRODUCT_NAME, "Alex"),
43 },
44 },
45 {
46 /* x86-mario, the Cr-48 pilot device from Google. */
47 .matches = {
48 DMI_MATCH(DMI_SYS_VENDOR, "IEC"),
49 DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
50 },
51 },
52 {
53 /* x86-zgb, the first Acer Chromebook. */
54 .matches = {
55 DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
56 DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
57 },
58 },
59 { }
60};
61MODULE_DEVICE_TABLE(dmi, chromeos_pstore_dmi_table);
62
63/*
64 * On x86 chromebooks/boxes, the firmware will keep the legacy VGA memory
65 * range untouched across reboots, so we use that to store our pstore
66 * contents for panic logs, etc.
67 */
68static struct ramoops_platform_data chromeos_ramoops_data = {
69 .mem_size = 0x100000,
70 .mem_address = 0xf00000,
71 .record_size = 0x20000,
72 .console_size = 0x20000,
73 .ftrace_size = 0x20000,
74 .dump_oops = 1,
75};
76
77static struct platform_device chromeos_ramoops = {
78 .name = "ramoops",
79 .dev = {
80 .platform_data = &chromeos_ramoops_data,
81 },
82};
83
84static int __init chromeos_pstore_init(void)
85{
86 if (dmi_check_system(chromeos_pstore_dmi_table))
87 return platform_device_register(&chromeos_ramoops);
88
89 return -ENODEV;
90}
91
92static void __exit chromeos_pstore_exit(void)
93{
94 platform_device_unregister(&chromeos_ramoops);
95}
96
97module_init(chromeos_pstore_init);
98module_exit(chromeos_pstore_exit);
99
100MODULE_DESCRIPTION("Chrome OS pstore module");
101MODULE_LICENSE("GPL");