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 bool card_blocked; 19 20 static int rfkill_set_block(void *data, bool blocked) 21 { 22 unsigned char cmd; 23 int r; 24 25 if (blocked == card_blocked) 26 return 0; 27 28 if (blocked) 29 cmd = EC_WLAN_ENTER_RESET; 30 else 31 cmd = EC_WLAN_LEAVE_RESET; 32 33 r = olpc_ec_cmd(cmd, NULL, 0, NULL, 0); 34 if (r == 0) 35 card_blocked = blocked; 36 37 return r; 38 } 39 40 static const struct rfkill_ops rfkill_ops = { 41 .set_block = rfkill_set_block, 42 }; 43 44 static int __devinit xo1_rfkill_probe(struct platform_device *pdev) 45 { 46 struct rfkill *rfk; 47 int r; 48 49 rfk = rfkill_alloc(pdev->name, &pdev->dev, RFKILL_TYPE_WLAN, 50 &rfkill_ops, NULL); 51 if (!rfk) 52 return -ENOMEM; 53 54 r = rfkill_register(rfk); 55 if (r) { 56 rfkill_destroy(rfk); 57 return r; 58 } 59 60 platform_set_drvdata(pdev, rfk); 61 return 0; 62 } 63 64 static int __devexit xo1_rfkill_remove(struct platform_device *pdev) 65 { 66 struct rfkill *rfk = platform_get_drvdata(pdev); 67 rfkill_unregister(rfk); 68 rfkill_destroy(rfk); 69 return 0; 70 } 71 72 static struct platform_driver xo1_rfkill_driver = { 73 .driver = { 74 .name = "xo1-rfkill", 75 .owner = THIS_MODULE, 76 }, 77 .probe = xo1_rfkill_probe, 78 .remove = __devexit_p(xo1_rfkill_remove), 79 }; 80 81 module_platform_driver(xo1_rfkill_driver); 82 83 MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>"); 84 MODULE_LICENSE("GPL"); 85 MODULE_ALIAS("platform:xo1-rfkill"); 86