static int pi433_remove(struct spi_device *spi) { struct pi433_device *device = spi_get_drvdata(spi); /* free GPIOs */ free_gpio(device); /* make sure ops on existing fds can abort cleanly */ device->spi = NULL; kthread_stop(device->tx_task_struct); device_destroy(pi433_class, device->devt); cdev_del(device->cdev); pi433_free_minor(device); kfree(device->rx_buffer); kfree(device); return 0; }
/** This method disables gpio to operate as pwm @param gpio - sets pin number according to numbering scheme GPIO is configured as input and all resources, allocated with the device are freed */ static int stop_pwm(const unsigned char gpio){ free_gpio(gpio); process_update(); return 0; }
static int pi433_probe(struct spi_device *spi) { struct pi433_device *device; int retval; /* setup spi parameters */ spi->mode = 0x00; spi->bits_per_word = 8; /* * spi->max_speed_hz = 10000000; * 1MHz already set by device tree overlay */ retval = spi_setup(spi); if (retval) { dev_dbg(&spi->dev, "configuration of SPI interface failed!\n"); return retval; } dev_dbg(&spi->dev, "spi interface setup: mode 0x%2x, %d bits per word, %dhz max speed", spi->mode, spi->bits_per_word, spi->max_speed_hz); /* Ping the chip by reading the version register */ retval = spi_w8r8(spi, 0x10); if (retval < 0) return retval; switch (retval) { case 0x24: dev_dbg(&spi->dev, "found pi433 (ver. 0x%x)", retval); break; default: dev_dbg(&spi->dev, "unknown chip version: 0x%x", retval); return -ENODEV; } /* Allocate driver data */ device = kzalloc(sizeof(*device), GFP_KERNEL); if (!device) return -ENOMEM; /* Initialize the driver data */ device->spi = spi; device->rx_active = false; device->tx_active = false; device->interrupt_rx_allowed = false; /* init rx buffer */ device->rx_buffer = kmalloc(MAX_MSG_SIZE, GFP_KERNEL); if (!device->rx_buffer) { retval = -ENOMEM; goto RX_failed; } /* init wait queues */ init_waitqueue_head(&device->tx_wait_queue); init_waitqueue_head(&device->rx_wait_queue); init_waitqueue_head(&device->fifo_wait_queue); /* init fifo */ INIT_KFIFO(device->tx_fifo); /* init mutexes and locks */ mutex_init(&device->tx_fifo_lock); mutex_init(&device->rx_lock); /* setup GPIO (including irq_handler) for the different DIOs */ retval = setup_gpio(device); if (retval) { dev_dbg(&spi->dev, "setup of GPIOs failed"); goto GPIO_failed; } /* setup the radio module */ retval = rf69_set_mode(spi, standby); if (retval < 0) goto minor_failed; retval = rf69_set_data_mode(spi, DATAMODUL_MODE_PACKET); if (retval < 0) goto minor_failed; retval = rf69_enable_amplifier(spi, MASK_PALEVEL_PA0); if (retval < 0) goto minor_failed; retval = rf69_disable_amplifier(spi, MASK_PALEVEL_PA1); if (retval < 0) goto minor_failed; retval = rf69_disable_amplifier(spi, MASK_PALEVEL_PA2); if (retval < 0) goto minor_failed; retval = rf69_set_output_power_level(spi, 13); if (retval < 0) goto minor_failed; retval = rf69_set_antenna_impedance(spi, fifty_ohm); if (retval < 0) goto minor_failed; /* determ minor number */ retval = pi433_get_minor(device); if (retval) { dev_dbg(&spi->dev, "get of minor number failed"); goto minor_failed; } /* create device */ device->devt = MKDEV(MAJOR(pi433_dev), device->minor); device->dev = device_create(pi433_class, &spi->dev, device->devt, device, "pi433.%d", device->minor); if (IS_ERR(device->dev)) { pr_err("pi433: device register failed\n"); retval = PTR_ERR(device->dev); goto device_create_failed; } else { dev_dbg(device->dev, "created device for major %d, minor %d\n", MAJOR(pi433_dev), device->minor); } /* start tx thread */ device->tx_task_struct = kthread_run(pi433_tx_thread, device, "pi433.%d_tx_task", device->minor); if (IS_ERR(device->tx_task_struct)) { dev_dbg(device->dev, "start of send thread failed"); retval = PTR_ERR(device->tx_task_struct); goto send_thread_failed; } /* create cdev */ device->cdev = cdev_alloc(); if (!device->cdev) { dev_dbg(device->dev, "allocation of cdev failed"); goto cdev_failed; } device->cdev->owner = THIS_MODULE; cdev_init(device->cdev, &pi433_fops); retval = cdev_add(device->cdev, device->devt, 1); if (retval) { dev_dbg(device->dev, "register of cdev failed"); goto del_cdev; } /* spi setup */ spi_set_drvdata(spi, device); return 0; del_cdev: cdev_del(device->cdev); cdev_failed: kthread_stop(device->tx_task_struct); send_thread_failed: device_destroy(pi433_class, device->devt); device_create_failed: pi433_free_minor(device); minor_failed: free_gpio(device); GPIO_failed: kfree(device->rx_buffer); RX_failed: kfree(device); return retval; }