| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Driver for NXP MCR20A 802.15.4 Wireless-PAN Networking controller |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2018 Xue Liu <liuxuenetmail@gmail.com> |
|---|
| 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 version 2 |
|---|
| 8 | | - * as published by the Free Software Foundation. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | | - * GNU General Public License for more details. |
|---|
| 14 | | - * |
|---|
| 15 | 6 | */ |
|---|
| 16 | 7 | #include <linux/kernel.h> |
|---|
| 17 | 8 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 132 | 123 | }; |
|---|
| 133 | 124 | |
|---|
| 134 | 125 | #define MCR20A_VALID_CHANNELS (0x07FFF800) |
|---|
| 135 | | - |
|---|
| 136 | | -struct mcr20a_platform_data { |
|---|
| 137 | | - int rst_gpio; |
|---|
| 138 | | -}; |
|---|
| 139 | | - |
|---|
| 140 | 126 | #define MCR20A_MAX_BUF (127) |
|---|
| 141 | 127 | |
|---|
| 142 | 128 | #define printdev(X) (&X->spi->dev) |
|---|
| .. | .. |
|---|
| 412 | 398 | struct spi_device *spi; |
|---|
| 413 | 399 | |
|---|
| 414 | 400 | struct ieee802154_hw *hw; |
|---|
| 415 | | - struct mcr20a_platform_data *pdata; |
|---|
| 416 | 401 | struct regmap *regmap_dar; |
|---|
| 417 | 402 | struct regmap *regmap_iar; |
|---|
| 418 | 403 | |
|---|
| .. | .. |
|---|
| 815 | 800 | if (!skb) |
|---|
| 816 | 801 | return; |
|---|
| 817 | 802 | |
|---|
| 818 | | - memcpy(skb_put(skb, len), lp->rx_buf, len); |
|---|
| 803 | + __skb_put_data(skb, lp->rx_buf, len); |
|---|
| 819 | 804 | ieee802154_rx_irqsafe(lp->hw, skb, lp->rx_lqi[0]); |
|---|
| 820 | 805 | |
|---|
| 821 | 806 | print_hex_dump_debug("mcr20a rx: ", DUMP_PREFIX_OFFSET, 16, 1, |
|---|
| .. | .. |
|---|
| 917 | 902 | } |
|---|
| 918 | 903 | break; |
|---|
| 919 | 904 | case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_SEQIRQ): |
|---|
| 920 | | - /* rx is starting */ |
|---|
| 921 | | - dev_dbg(printdev(lp), "RX is starting\n"); |
|---|
| 922 | | - mcr20a_handle_rx(lp); |
|---|
| 905 | + /* rx is starting */ |
|---|
| 906 | + dev_dbg(printdev(lp), "RX is starting\n"); |
|---|
| 907 | + mcr20a_handle_rx(lp); |
|---|
| 923 | 908 | break; |
|---|
| 924 | 909 | case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_TXIRQ | DAR_IRQSTS1_SEQIRQ): |
|---|
| 925 | 910 | if (lp->is_tx) { |
|---|
| .. | .. |
|---|
| 980 | 965 | } |
|---|
| 981 | 966 | |
|---|
| 982 | 967 | return IRQ_HANDLED; |
|---|
| 983 | | -} |
|---|
| 984 | | - |
|---|
| 985 | | -static int mcr20a_get_platform_data(struct spi_device *spi, |
|---|
| 986 | | - struct mcr20a_platform_data *pdata) |
|---|
| 987 | | -{ |
|---|
| 988 | | - int ret = 0; |
|---|
| 989 | | - |
|---|
| 990 | | - if (!spi->dev.of_node) |
|---|
| 991 | | - return -EINVAL; |
|---|
| 992 | | - |
|---|
| 993 | | - pdata->rst_gpio = of_get_named_gpio(spi->dev.of_node, "rst_b-gpio", 0); |
|---|
| 994 | | - dev_dbg(&spi->dev, "rst_b-gpio: %d\n", pdata->rst_gpio); |
|---|
| 995 | | - |
|---|
| 996 | | - return ret; |
|---|
| 997 | 968 | } |
|---|
| 998 | 969 | |
|---|
| 999 | 970 | static void mcr20a_hw_setup(struct mcr20a_local *lp) |
|---|
| .. | .. |
|---|
| 1255 | 1226 | { |
|---|
| 1256 | 1227 | struct ieee802154_hw *hw; |
|---|
| 1257 | 1228 | struct mcr20a_local *lp; |
|---|
| 1258 | | - struct mcr20a_platform_data *pdata; |
|---|
| 1229 | + struct gpio_desc *rst_b; |
|---|
| 1259 | 1230 | int irq_type; |
|---|
| 1260 | 1231 | int ret = -ENOMEM; |
|---|
| 1261 | 1232 | |
|---|
| .. | .. |
|---|
| 1266 | 1237 | return -EINVAL; |
|---|
| 1267 | 1238 | } |
|---|
| 1268 | 1239 | |
|---|
| 1269 | | - pdata = kmalloc(sizeof(*pdata), GFP_KERNEL); |
|---|
| 1270 | | - if (!pdata) |
|---|
| 1271 | | - return -ENOMEM; |
|---|
| 1272 | | - |
|---|
| 1273 | | - /* set mcr20a platform data */ |
|---|
| 1274 | | - ret = mcr20a_get_platform_data(spi, pdata); |
|---|
| 1275 | | - if (ret < 0) { |
|---|
| 1276 | | - dev_crit(&spi->dev, "mcr20a_get_platform_data failed.\n"); |
|---|
| 1277 | | - goto free_pdata; |
|---|
| 1278 | | - } |
|---|
| 1279 | | - |
|---|
| 1280 | | - /* init reset gpio */ |
|---|
| 1281 | | - if (gpio_is_valid(pdata->rst_gpio)) { |
|---|
| 1282 | | - ret = devm_gpio_request_one(&spi->dev, pdata->rst_gpio, |
|---|
| 1283 | | - GPIOF_OUT_INIT_HIGH, "reset"); |
|---|
| 1284 | | - if (ret) |
|---|
| 1285 | | - goto free_pdata; |
|---|
| 1240 | + rst_b = devm_gpiod_get(&spi->dev, "rst_b", GPIOD_OUT_HIGH); |
|---|
| 1241 | + if (IS_ERR(rst_b)) { |
|---|
| 1242 | + ret = PTR_ERR(rst_b); |
|---|
| 1243 | + if (ret != -EPROBE_DEFER) |
|---|
| 1244 | + dev_err(&spi->dev, "Failed to get 'rst_b' gpio: %d", ret); |
|---|
| 1245 | + return ret; |
|---|
| 1286 | 1246 | } |
|---|
| 1287 | 1247 | |
|---|
| 1288 | 1248 | /* reset mcr20a */ |
|---|
| 1289 | | - if (gpio_is_valid(pdata->rst_gpio)) { |
|---|
| 1290 | | - usleep_range(10, 20); |
|---|
| 1291 | | - gpio_set_value_cansleep(pdata->rst_gpio, 0); |
|---|
| 1292 | | - usleep_range(10, 20); |
|---|
| 1293 | | - gpio_set_value_cansleep(pdata->rst_gpio, 1); |
|---|
| 1294 | | - usleep_range(120, 240); |
|---|
| 1295 | | - } |
|---|
| 1249 | + usleep_range(10, 20); |
|---|
| 1250 | + gpiod_set_value_cansleep(rst_b, 1); |
|---|
| 1251 | + usleep_range(10, 20); |
|---|
| 1252 | + gpiod_set_value_cansleep(rst_b, 0); |
|---|
| 1253 | + usleep_range(120, 240); |
|---|
| 1296 | 1254 | |
|---|
| 1297 | 1255 | /* allocate ieee802154_hw and private data */ |
|---|
| 1298 | 1256 | hw = ieee802154_alloc_hw(sizeof(*lp), &mcr20a_hw_ops); |
|---|
| 1299 | 1257 | if (!hw) { |
|---|
| 1300 | 1258 | dev_crit(&spi->dev, "ieee802154_alloc_hw failed\n"); |
|---|
| 1301 | | - ret = -ENOMEM; |
|---|
| 1302 | | - goto free_pdata; |
|---|
| 1259 | + return ret; |
|---|
| 1303 | 1260 | } |
|---|
| 1304 | 1261 | |
|---|
| 1305 | 1262 | /* init mcr20a local data */ |
|---|
| 1306 | 1263 | lp = hw->priv; |
|---|
| 1307 | 1264 | lp->hw = hw; |
|---|
| 1308 | 1265 | lp->spi = spi; |
|---|
| 1309 | | - lp->spi->dev.platform_data = pdata; |
|---|
| 1310 | | - lp->pdata = pdata; |
|---|
| 1311 | 1266 | |
|---|
| 1312 | 1267 | /* init ieee802154_hw */ |
|---|
| 1313 | 1268 | hw->parent = &spi->dev; |
|---|
| .. | .. |
|---|
| 1376 | 1331 | |
|---|
| 1377 | 1332 | free_dev: |
|---|
| 1378 | 1333 | ieee802154_free_hw(lp->hw); |
|---|
| 1379 | | -free_pdata: |
|---|
| 1380 | | - kfree(pdata); |
|---|
| 1381 | 1334 | |
|---|
| 1382 | 1335 | return ret; |
|---|
| 1383 | 1336 | } |
|---|