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 goto fail_shutdown_name; 135 } 136 } 137 138 if (gpio_is_valid(pdata->reset_gpio)) { 139 ret = gpio_request(pdata->reset_gpio, rfkill->reset_name); 140 if (ret) { 141 pr_warn("%s: failed to get reset gpio.\n", __func__); 142 goto fail_clock; 143 } 144 } 145 146 if (gpio_is_valid(pdata->shutdown_gpio)) { 147 ret = gpio_request(pdata->shutdown_gpio, rfkill->shutdown_name); 148 if (ret) { 149 pr_warn("%s: failed to get shutdown gpio.\n", __func__); 150 goto fail_reset; 151 } 152 } 153 154 rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type, 155 &rfkill_gpio_ops, rfkill); 156 if (!rfkill->rfkill_dev) 157 goto fail_shutdown; 158 159 ret = rfkill_register(rfkill->rfkill_dev); 160 if (ret < 0) 161 goto fail_rfkill; 162 163 platform_set_drvdata(pdev, rfkill); 164 165 dev_info(&pdev->dev, "%s device registered.\n", pdata->name); 166 167 return 0; 168 169 fail_rfkill: 170 rfkill_destroy(rfkill->rfkill_dev); 171 fail_shutdown: 172 if (gpio_is_valid(pdata->shutdown_gpio)) 173 gpio_free(pdata->shutdown_gpio); 174 fail_reset: 175 if (gpio_is_valid(pdata->reset_gpio)) 176 gpio_free(pdata->reset_gpio); 177 fail_clock: 178 if (rfkill->pwr_clk) 179 clk_put(rfkill->pwr_clk); 180 fail_shutdown_name: 181 kfree(rfkill->shutdown_name); 182 fail_reset_name: 183 kfree(rfkill->reset_name); 184 fail_alloc: 185 kfree(rfkill); 186 187 return ret; 188 } 189 190 static int rfkill_gpio_remove(struct platform_device *pdev) 191 { 192 struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev); 193 struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; 194 195 if (pdata->gpio_runtime_close) 196 pdata->gpio_runtime_close(pdev); 197 rfkill_unregister(rfkill->rfkill_dev); 198 rfkill_destroy(rfkill->rfkill_dev); 199 if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) 200 gpio_free(rfkill->pdata->shutdown_gpio); 201 if (gpio_is_valid(rfkill->pdata->reset_gpio)) 202 gpio_free(rfkill->pdata->reset_gpio); 203 if (rfkill->pwr_clk && PWR_CLK_ENABLED(rfkill)) 204 clk_disable(rfkill->pwr_clk); 205 if (rfkill->pwr_clk) 206 clk_put(rfkill->pwr_clk); 207 kfree(rfkill->shutdown_name); 208 kfree(rfkill->reset_name); 209 kfree(rfkill); 210 211 return 0; 212 } 213 214 static struct platform_driver rfkill_gpio_driver = { 215 .probe = rfkill_gpio_probe, 216 .remove = rfkill_gpio_remove, 217 .driver = { 218 .name = "rfkill_gpio", 219 .owner = THIS_MODULE, 220 }, 221 }; 222 223 module_platform_driver(rfkill_gpio_driver); 224 225 MODULE_DESCRIPTION("gpio rfkill"); 226 MODULE_AUTHOR("NVIDIA"); 227 MODULE_LICENSE("GPL"); 228