1 /* 2 * Support for rfkill through the OLPC XO-1 laptop embedded controller 3 * 4 * Copyright (C) 2010 One Laptop per Child 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; either version 2 of the License, or 9 * (at your option) any later version. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 #include <linux/rfkill.h> 15 16 #include <asm/olpc.h> 17 18 static int rfkill_set_block(void *data, bool blocked) 19 { 20 unsigned char cmd; 21 if (blocked) 22 cmd = EC_WLAN_ENTER_RESET; 23 else 24 cmd = EC_WLAN_LEAVE_RESET; 25 26 return olpc_ec_cmd(cmd, NULL, 0, NULL, 0); 27 } 28 29 static const struct rfkill_ops rfkill_ops = { 30 .set_block = rfkill_set_block, 31 }; 32 33 static int __devinit xo1_rfkill_probe(struct platform_device *pdev) 34 { 35 struct rfkill *rfk; 36 int r; 37 38 rfk = rfkill_alloc(pdev->name, &pdev->dev, RFKILL_TYPE_WLAN, 39 &rfkill_ops, NULL); 40 if (!rfk) 41 return -ENOMEM; 42 43 r = rfkill_register(rfk); 44 if (r) { 45 rfkill_destroy(rfk); 46 return r; 47 } 48 49 platform_set_drvdata(pdev, rfk); 50 return 0; 51 } 52 53 static int __devexit xo1_rfkill_remove(struct platform_device *pdev) 54 { 55 struct rfkill *rfk = platform_get_drvdata(pdev); 56 rfkill_unregister(rfk); 57 rfkill_destroy(rfk); 58 return 0; 59 } 60 61 static struct platform_driver xo1_rfkill_driver = { 62 .driver = { 63 .name = "xo1-rfkill", 64 .owner = THIS_MODULE, 65 }, 66 .probe = xo1_rfkill_probe, 67 .remove = __devexit_p(xo1_rfkill_remove), 68 }; 69 70 module_platform_driver(xo1_rfkill_driver); 71 72 MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>"); 73 MODULE_LICENSE("GPL"); 74 MODULE_ALIAS("platform:xo1-rfkill"); 75