+/*----------------------------------------------------------------------*/
+#define param_check_irq(name, p) /* define own irq type */
+#define PARAM_IRQ_VAL_NONE -1 /* value, if 'none' irq is used */
+#define PARAM_IRQ_VAL_AUTO -2 /* value, if 'auto' irq is used */
+#define PARAM_IRQ_NAME_NONE "none" /* string, if no irq is used */
+#define PARAM_IRQ_NAME_AUTO "auto" /* string, if irq is automatically determined by the parport irq line */
+
+/**
+ * special irq parameter type
+ * The irq type allows setting of irq numbers in the range of all positive integer values
+ * and additionally the values "none" and "auto". These extra values will be converted into
+ * corresponding negative values -1 and -2. As exception is also the value -1 allowed, which
+ * will be seen as "none".
+ */
+int param_set_irq(const char *pbuf, struct kernel_param *kp)
+{
+ int number;
+
+ if (0 == strncmp(pbuf, PARAM_IRQ_NAME_NONE, sizeof(PARAM_IRQ_NAME_NONE))) {
+ number = PARAM_IRQ_VAL_NONE;
+ } else if (0 == strncmp(pbuf, PARAM_IRQ_NAME_AUTO, sizeof(PARAM_IRQ_NAME_AUTO))) {
+ number = PARAM_IRQ_VAL_AUTO;
+ } else {
+ char *ep;
+ number = simple_strtol(pbuf, &ep, 0);
+ if (ep != pbuf) {
+ if ((0 > number) && (PARAM_IRQ_VAL_NONE != number))
+ return -EINVAL;
+ } else
+ return -EINVAL;
+ }
+ *(int *)kp->arg = number;
+ return 0;
+}
+
+int param_get_irq(char *pbuf, struct kernel_param *kp)
+{
+ int value = *(int *)kp->arg;
+ if (PARAM_IRQ_VAL_NONE == value)
+ return sprintf((char *)pbuf, "%s", PARAM_IRQ_NAME_NONE);
+ else if (PARAM_IRQ_VAL_AUTO == value)
+ return sprintf((char *)pbuf, "%s", PARAM_IRQ_NAME_AUTO);
+ else if (0 <= value)
+ return sprintf((char *)pbuf, "%d", value);
+ else
+ return -EINVAL;
+}
+
+/**
+ * copies src to dest string up to count characters or until a character is found
+ * which matches the delim string set. As the return value will be returned the next
+ * address of src, which can be used for the next stnarr of NULL if the found string
+ * was longer than count.
+ */
+const char *strnarr(char *dst, const char *src, const char *dlim, size_t count)
+{
+ int i;
+ for(i=0; i<count; i++) {
+ if (*src == '\0') {
+ *dst='\0';
+ return src;
+ }
+ if (strchr(dlim, *src)!=NULL) {
+ *dst='\0';
+ return ++src;
+ }
+ *dst++=*src++;
+ }
+ *--dst='\0'; /* add missing line end */
+ return NULL;
+}
+
+
+/**
+ * spi parport registers the SPI devices, defined by the given module load parameters.
+ * Although the bit_per_word value is strongly recommended to set by the protocol driver
+ * itself, spi_parport_register_spi_devices supports that for buggy drivers like the lm70.c
+ * SPI temperature driver. But that requires using spi_add_device instead of spi_new_device
+ * to ensure setting that bit_per_word value just before the protocol driver may change and
+ * use that value for probing the connected SPI device hardware.
+ *
+ * Additionally all SPI data structures will be first setup and all used spi chipselects will
+ * be initialized to its inactive state before the spi_add_device is called. This ensures that
+ * no early spi device usage by a spi protocol drivers probe sequence may toggle the spi clock,
+ * although there might be another spi device at the bus, which has not yet properly setup its
+ * chip select state as inactive.
+ */
+static int spi_parport_register_spi_devices(struct spi_parport *pp)
+{
+ const char *modalias_param=spi_modalias;
+ struct spi_device *spi[SPI_DEV_MAX]; /* fill up here all settings instead using a board_info struct */
+ int i; /* loop counter */
+ int max; /* maximum loop value */
+
+ /* loop over all SPI device informations found in module parameter settings */
+ for (i=0; (modalias_param[0]!='\0') && (i<SPI_DEV_MAX); i++) {
+ spi[i] = spi_alloc_device(pp->bitbang.master); /* kzalloc memory and add device to master controller */
+ if (NULL == spi[i]) {
+ while (i > 0) {
+ spi_dev_put(spi[--i]); /* free all spi devices from former spi_alloc_device */
+ }
+ return -ENOMEM;
+ }
+
+ /*
+ * first copy the modalias parameter
+ */
+ modalias_param=strnarr(spi[i]->modalias, modalias_param, " ,", sizeof(spi[i]->modalias));
+ if (NULL == spi[i]->modalias) {
+ pr_err("%s: %d given modalias name is too long! See only that '%s'!\n",
+ DRVNAME, i, spi[i]->modalias);
+ while (i >= 0) {
+ spi_dev_put(spi[i--]); /* free all spi devices */
+ }
+ return -EINVAL;
+ }
+
+ /*
+ * now setup the rest as it would be done by
+ * the spi_new_device from a given board_info
+ * structure.
+ */
+ spi[i]->max_speed_hz = SPI_PARPORT_MAX_SPEED;
+ spi[i]->chip_select = i;
+ spi[i]->master = pp->bitbang.master;
+ spi[i]->controller_data = pp; /* enable access to primary controller data */
+ spi[i]->controller_state = NULL; /* init state like in new_spi_device */
+ spi[i]->mode = spi_mode[i];
+ spi[i]->irq = spi_irq[i];
+ spi[i]->bits_per_word = spi_bits[i]; /* must normally be done by protocol driver */
+ spi[i]->dev.platform_data = (void *)NULL; /* data area of SPI protocol driver,
+ hot plug drivers must do that itself */
+ /*
+ * first only initialize the chipselect
+ * for that spi device to set it inactive
+ */
+ spi_parport_chipselect(spi[i], BITBANG_CS_INACTIVE);
+ if (spi_mode_cnt < (i+1)) {
+ pr_warning("%s: No spi mode parameter given for device %d with driver '%s'. "
+ "Will use default setting: %d\n",
+ DRVNAME, i, spi[i]->modalias, spi[i]->mode);
+ }
+ }
+ /* additional parameter checks and possibly logged warnings */
+ if (modalias_param[0]!='\0'){
+ pr_warning("%s: Found more modalias parameters of SPI devices than allowed (max: %d)!\n",
+ DRVNAME, SPI_DEV_MAX);
+ }
+ if (spi_mode_cnt > i) {
+ pr_warning("%s: Found further %d mode parameters than SPI devices used or no SPI mode defined!\n",
+ DRVNAME, spi_mode_cnt-i);
+ }
+ /*
+ * Now all spi device structures are setup and all used
+ * chipselects are initialized. We will now add the
+ * spi devices for probing and usage. We use the same
+ * ordering!
+ */
+ max = i; /* remember the last value */
+ for (i=0; i<max; i++) {
+ int err;
+
+ err = spi_add_device(spi[i]);
+ if (err < 0) {
+ /*
+ * free all further spi devices too.
+ * all already added spi devices will be freed
+ * later with the final call to spi_master_put
+ */
+ while (i<max) {
+ spi_dev_put(spi[i++]);
+ }
+ pr_err("%s: spi_new_device failed!\n", DRVNAME);
+ return -ENODEV;
+ }
+ if (0 <= spi[i]->irq) {
+ pr_info("%s: SPI device successfully registered at bus %s as device %s with mode 0x%x,"
+ " %d bits/word, irq %d\n", DRVNAME, spi[i]->dev.bus_id, spi[i]->modalias,
+ spi[i]->mode, spi[i]->bits_per_word, spi[i]->irq);
+ } else {
+ pr_info("%s: SPI device successfully registered at bus %s as device %s with mode 0x%x,"
+ " %d bits/word, no irq\n", DRVNAME, spi[i]->dev.bus_id, spi[i]->modalias,
+ spi[i]->mode, spi[i]->bits_per_word);
+ }
+ }
+ return i;
+}