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