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 17static bool card_blocked; 18 19static 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 39static const struct rfkill_ops rfkill_ops = { 40 .set_block = rfkill_set_block, 41}; 42 43static 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 63static 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 71static 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 79module_platform_driver(xo1_rfkill_driver); 80 81MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>"); 82MODULE_LICENSE("GPL"); 83MODULE_ALIAS("platform:xo1-rfkill"); 84