1 /* 2 * Copyright (c) 2011, NVIDIA Corporation. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19 #include <linux/gpio.h> 20 #include <linux/init.h> 21 #include <linux/kernel.h> 22 #include <linux/module.h> 23 #include <linux/rfkill.h> 24 #include <linux/platform_device.h> 25 #include <linux/clk.h> 26 #include <linux/slab.h> 27 28 #include <linux/rfkill-gpio.h> 29 30 enum rfkill_gpio_clk_state { 31 UNSPECIFIED = 0, 32 PWR_ENABLED, 33 PWR_DISABLED 34 }; 35 36 #define PWR_CLK_SET(_RF, _EN) \ 37 ((_RF)->pwr_clk_enabled = (!(_EN) ? PWR_ENABLED : PWR_DISABLED)) 38 #define PWR_CLK_ENABLED(_RF) ((_RF)->pwr_clk_enabled == PWR_ENABLED) 39 #define PWR_CLK_DISABLED(_RF) ((_RF)->pwr_clk_enabled != PWR_ENABLED) 40 41 struct rfkill_gpio_data { 42 struct rfkill_gpio_platform_data *pdata; 43 struct rfkill *rfkill_dev; 44 char *reset_name; 45 char *shutdown_name; 46 enum rfkill_gpio_clk_state pwr_clk_enabled; 47 struct clk *pwr_clk; 48 }; 49 50 static int rfkill_gpio_set_power(void *data, bool blocked) 51 { 52 struct rfkill_gpio_data *rfkill = data; 53 54 if (blocked) { 55 if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) 56 gpio_direction_output(rfkill->pdata->shutdown_gpio, 0); 57 if (gpio_is_valid(rfkill->pdata->reset_gpio)) 58 gpio_direction_output(rfkill->pdata->reset_gpio, 0); 59 if (rfkill->pwr_clk && PWR_CLK_ENABLED(rfkill)) 60 clk_disable(rfkill->pwr_clk); 61 } else { 62 if (rfkill->pwr_clk && PWR_CLK_DISABLED(rfkill)) 63 clk_enable(rfkill->pwr_clk); 64 if (gpio_is_valid(rfkill->pdata->reset_gpio)) 65 gpio_direction_output(rfkill->pdata->reset_gpio, 1); 66 if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) 67 gpio_direction_output(rfkill->pdata->shutdown_gpio, 1); 68 } 69 70 if (rfkill->pwr_clk) 71 PWR_CLK_SET(rfkill, blocked); 72 73 return 0; 74 } 75 76 static const struct rfkill_ops rfkill_gpio_ops = { 77 .set_block = rfkill_gpio_set_power, 78 }; 79 80 static int rfkill_gpio_probe(struct platform_device *pdev) 81 { 82 struct rfkill_gpio_data *rfkill; 83 struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; 84 int ret = 0; 85 int len = 0; 86 87 if (!pdata) { 88 pr_warn("%s: No platform data specified\n", __func__); 89 return -EINVAL; 90 } 91 92 /* make sure at-least one of the GPIO is defined and that 93 * a name is specified for this instance */ 94 if (!pdata->name || (!gpio_is_valid(pdata->reset_gpio) && 95 !gpio_is_valid(pdata->shutdown_gpio))) { 96 pr_warn("%s: invalid platform data\n", __func__); 97 return -EINVAL; 98 } 99 100 rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL); 101 if (!rfkill) 102 return -ENOMEM; 103 104 if (pdata->gpio_runtime_setup) { 105 ret = pdata->gpio_runtime_setup(pdev); 106 if (ret) { 107 pr_warn("%s: can't set up gpio\n", __func__); 108 goto fail_alloc; 109 } 110 } 111 112 rfkill->pdata = pdata; 113 114 len = strlen(pdata->name); 115 rfkill->reset_name = kzalloc(len + 7, GFP_KERNEL); 116 if (!rfkill->reset_name) { 117 ret = -ENOMEM; 118 goto fail_alloc; 119 } 120 121 rfkill->shutdown_name = kzalloc(len + 10, GFP_KERNEL); 122 if (!rfkill->shutdown_name) { 123 ret = -ENOMEM; 124 goto fail_reset_name; 125 } 126 127 snprintf(rfkill->reset_name, len + 6 , "%s_reset", pdata->name); 128 snprintf(rfkill->shutdown_name, len + 9, "%s_shutdown", pdata->name); 129 130 if (pdata->power_clk_name) { 131 rfkill->pwr_clk = clk_get(&pdev->dev, pdata->power_clk_name); 132 if (IS_ERR(rfkill->pwr_clk)) { 133 pr_warn("%s: can't find pwr_clk.\n", __func__); 134 ret = PTR_ERR(rfkill->pwr_clk); 135 goto fail_shutdown_name; 136 } 137 } 138 139 if (gpio_is_valid(pdata->reset_gpio)) { 140 ret = gpio_request(pdata->reset_gpio, rfkill->reset_name); 141 if (ret) { 142 pr_warn("%s: failed to get reset gpio.\n", __func__); 143 goto fail_clock; 144 } 145 } 146 147 if (gpio_is_valid(pdata->shutdown_gpio)) { 148 ret = gpio_request(pdata->shutdown_gpio, rfkill->shutdown_name); 149 if (ret) { 150 pr_warn("%s: failed to get shutdown gpio.\n", __func__); 151 goto fail_reset; 152 } 153 } 154 155 rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type, 156 &rfkill_gpio_ops, rfkill); 157 if (!rfkill->rfkill_dev) { 158 ret = -ENOMEM; 159 goto fail_shutdown; 160 } 161 162 ret = rfkill_register(rfkill->rfkill_dev); 163 if (ret < 0) 164 goto fail_rfkill; 165 166 platform_set_drvdata(pdev, rfkill); 167 168 dev_info(&pdev->dev, "%s device registered.\n", pdata->name); 169 170 return 0; 171 172 fail_rfkill: 173 rfkill_destroy(rfkill->rfkill_dev); 174 fail_shutdown: 175 if (gpio_is_valid(pdata->shutdown_gpio)) 176 gpio_free(pdata->shutdown_gpio); 177 fail_reset: 178 if (gpio_is_valid(pdata->reset_gpio)) 179 gpio_free(pdata->reset_gpio); 180 fail_clock: 181 if (rfkill->pwr_clk) 182 clk_put(rfkill->pwr_clk); 183 fail_shutdown_name: 184 kfree(rfkill->shutdown_name); 185 fail_reset_name: 186 kfree(rfkill->reset_name); 187 fail_alloc: 188 kfree(rfkill); 189 190 return ret; 191 } 192 193 static int rfkill_gpio_remove(struct platform_device *pdev) 194 { 195 struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev); 196 struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; 197 198 if (pdata->gpio_runtime_close) 199 pdata->gpio_runtime_close(pdev); 200 rfkill_unregister(rfkill->rfkill_dev); 201 rfkill_destroy(rfkill->rfkill_dev); 202 if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) 203 gpio_free(rfkill->pdata->shutdown_gpio); 204 if (gpio_is_valid(rfkill->pdata->reset_gpio)) 205 gpio_free(rfkill->pdata->reset_gpio); 206 if (rfkill->pwr_clk && PWR_CLK_ENABLED(rfkill)) 207 clk_disable(rfkill->pwr_clk); 208 if (rfkill->pwr_clk) 209 clk_put(rfkill->pwr_clk); 210 kfree(rfkill->shutdown_name); 211 kfree(rfkill->reset_name); 212 kfree(rfkill); 213 214 return 0; 215 } 216 217 static struct platform_driver rfkill_gpio_driver = { 218 .probe = rfkill_gpio_probe, 219 .remove = rfkill_gpio_remove, 220 .driver = { 221 .name = "rfkill_gpio", 222 .owner = THIS_MODULE, 223 }, 224 }; 225 226 module_platform_driver(rfkill_gpio_driver); 227 228 MODULE_DESCRIPTION("gpio rfkill"); 229 MODULE_AUTHOR("NVIDIA"); 230 MODULE_LICENSE("GPL"); 231