* supported modes: dev->dev->port->modes; Depending on the mode flags we change
* the mode value in the dev->dev->port->base_hi+0x02; Register, which is the ECR
* (extended control register). So first set to SPP (standard parport mode)
- * 1. first setup all CS, because spi_new_device or spi_add_device will call
- * probe fkt of the SPI protocoll driver. This might initiate a SPI transfer
- * and triggers the SCLK, which is worse for other chips on the SPI-BUS using
- * the wrong CS polarity
- * 2. use spi_add_device instead of spi_new_device. That's the only chance
- * to setup the also the SPI bits per word value, just before any transaction
- * might be initiated with the SPI probe fkt of the SPI protocol driver.
- * Setting this spi->bits_per_word value afterwards might be here too late.
- * Note that bits_per_word is normally has to be set normally by the protocoll
- * driver (e.g. a bad style of the lm70.c driver, which guess that the value is
- * setup afterwards)
- * Therefore we MUST support a mode, where NOTHING will be changed!
- * 3. support better irq via array load parameter and values like AUTO, NONE. Additionally
+ * 1. support better irq via array load parameter and values like AUTO, NONE. Additionally
* don't free any interrupt, if no interrupt might be requested
- * 4. output warning, if open mode, bits values after finish init
- * 5. test spi modes
*
* Note: - SPI_LSB_FIRST is not yet supported and would need own txrx functions
* - SPI_LOOP is supported, but requires tx before rx in own transfer functions
* D1 3 --> D1 (1 << 1) MOSI
* D2 4 --> D2 (1 << 2) nCS0
* D3 5 --> D3 (1 << 3) nCS1
- * D4 6 --> D4 (1 << 4) --
- * D5 7 --> D5 (1 << 5) --
+ * D4 6 --> D4 (1 << 4) nCS2
+ * D5 7 --> D5 (1 << 5) nCS3
* D6 8 --> D6 (1 << 6) --
* D7 9 --> D7 (1 << 7) --
* nAckn 10 <-- S6 PARPORT_STATUS_ACK
// MODULE PARAMETERS
//*****************************************************************************
#define DRVNAME "spi_parport" /* name of the driver */
-#define DRIVER_VERSION "0.2" /* helps identifing different versions of that driver */
+#define DRIVER_VERSION "0.3" /* helps identifying different versions of that driver */
#define SPI_PARPORT_SCLK (1 << 0) /* SPI Clock on parport D0 or pin 2 */
#define SPI_PARPORT_MOSI (1 << 1) /* SPI MOSI on parport D1 or pin 3 */
/*
** parport data bit input function, only need for loop back mode
-** Note: Neiter the dcache is here updated nor the value is read from that dcache
-** to ensure similar system timing bahaviour as in standard MISO read mode.
+** Note: Neither the dcache is here updated nor the value is read from that dcache
+** to ensure similar system timing behavior as in standard MISO read mode.
*/
static inline int spi_parport_data_get(struct spi_parport *pp, unsigned mask)
{
/*
-** spi parport registers SPI devices, defined by the given module load parameters.
+** 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;
- int i=0;
-
+ 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 */
+#if 1
/* loop over all SPI device informations found in module parameter settings */
- while ((modalias_param[0]!='\0') && (i<SPI_DEV_MAX)) {
- struct spi_board_info chip; /* parport SPI board description placeholder*/
- struct spi_device *proxy; /* just need to check spi device result and add additional 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 = pp->irq; /* TODO: separate IRQ setting */
+ 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!\n",
+ DRVNAME, spi_mode_cnt-i);
+ }
+ if (spi_bits_cnt > i) {
+ pr_warning("%s: Found further %d bits parameters than SPI devices used!\n",
+ DRVNAME, spi_bits_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;
+ }
+ pr_info("%s: SPI device successfully registered at bus %s as device %s with %d bits/word\n", DRVNAME,
+ spi[i]->dev.bus_id, spi[i]->modalias, spi[i]->bits_per_word);
+ }
+ #else
+ i=0;
+ while ((modalias_param[0]!='\0') && (i<SPI_DEV_MAX)) {
+ struct spi_device *proxy; /* just need to check spi device result and add additional settings */
+ struct spi_board_info chip; /* parport SPI board description placeholder*/
+
modalias_param=strnarr(chip.modalias, modalias_param, " ,", sizeof(chip.modalias));
if (modalias_param==NULL) {
pr_err("%s: %d given modalias name is too long! See only that '%s'!\n", DRVNAME, i, chip.modalias);
pr_err("%s: spi_new_device failed!\n", DRVNAME);
return -ENODEV;
}
- if (spi_bits_cnt < i) {
- pr_warning("%s: No spi bits per word parameter given for device %d with driver '%s'. "
- "Will use default setting: %d\n",
- DRVNAME, i, chip.modalias, spi_bits[i-1]);
- }
- proxy->bits_per_word=spi_bits[i-1];
pr_info("%s: SPI device successfully registered at bus %s as device %s with %d bits/word\n", DRVNAME,
proxy->dev.bus_id, chip.modalias, proxy->bits_per_word);
- }
- if (modalias_param[0]!='\0'){
- pr_warning("%s: Found more modalias parameters of SPI devices than allowed (max: %d)!\n",
- DRVNAME, SPI_DEV_MAX);
- }
- return i;
+ }
+ if (modalias_param[0]!='\0'){
+ pr_warning("%s: Found more modalias parameters of SPI devices than allowed (max: %d)!\n",
+ DRVNAME, SPI_DEV_MAX);
+ }
+#endif
+ return i;
}
/***************************************************************************
}
/* ----------------- SPI ParPort init ---------------- */
- /* cache initialisation just preventing changing unused bits */
+ /* cache initialization just preventing changing unused bits */
pp->dcache = parport_read_data(pp->port);
if(irq >= 0) {