@@ -7,25 +7,20 @@ struct spi_device;
* struct ep93xx_spi_info - EP93xx specific SPI descriptor
* @num_chipselect: number of chip selects on this board, must be
* at least one
- * @cs_control: chip select control function. Can be %NULL if not needed.
- *
- * This structure is passed from board support files to EP93xx SPI controller
- * driver. It provides callback hook to control chip select lines that are
- * allocated in board support files during the board initialization.
*/
struct ep93xx_spi_info {
int num_chipselect;
- /*
- * cs_control() - control board chipselect GPIO lines
- * @spi: SPI device whose chipselect is controlled
- * @value: value to set the chip select line to
- *
- * This function is used to control board specific chip select lines.
- * @value is either %0 or %1.
- *
- * This function is called from thread context and can sleep if
- * necessary.
- */
+};
+
+/**
+ * struct ep93xx_spi_chip_ops - operation callbacks for SPI slave device
+ * @setup: setup the chip select mechanism
+ * @cleanup: cleanup the chip select mechanism
+ * @cs_control: control the device chip select
+ */
+struct ep93xx_spi_chip_ops {
+ int (*setup)(struct spi_device *spi);
+ void (*cleanup)(struct spi_device *spi);
void (*cs_control)(struct spi_device *spi, int value);
};
@@ -84,7 +84,6 @@
* @rx: current byte in transfer to receive
* @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one
* frame decreases this level and sending one frame increases it.
- * @cs_control: chip select control function
*
* This structure holds EP93xx SPI controller specific information. When
* @running is %true, driver accepts transfer requests from protocol drivers.
@@ -113,7 +112,6 @@ struct ep93xx_spi {
size_t tx;
size_t rx;
size_t fifo_level;
- void (*cs_control)(struct spi_device *, int);
};
/**
@@ -123,6 +121,7 @@ struct ep93xx_spi {
* @div_cpsr: cpsr (pre-scaler) divider
* @div_scr: scr divider
* @dss: bits per word (4 - 16 bits)
+ * @ops: private chip operations
*
* This structure is used to store hardware register specific settings for each
* SPI device. Settings are written to hardware by function
@@ -134,6 +133,7 @@ struct ep93xx_spi_chip {
u8 div_cpsr;
u8 div_scr;
u8 dss;
+ struct ep93xx_spi_chip_ops *ops;
};
/* converts bits per word to CR0.DSS value */
@@ -283,7 +283,6 @@ static int ep93xx_spi_calc_divisors(cons
/**
* ep93xx_spi_cs_control() - controls chipselect for given device
- * @espi: ep93xx SPI controller struct
* @spi: SPI device to select/deselect
* @control: select (%true) / deselect (%false)
*
@@ -291,14 +290,13 @@ static int ep93xx_spi_calc_divisors(cons
*
* Note that this function is called from a thread context and can sleep.
*/
-static inline void ep93xx_spi_cs_control(const struct ep93xx_spi *espi,
- struct spi_device *spi,
- bool control)
+static void ep93xx_spi_cs_control(struct spi_device *spi, bool control)
{
+ struct ep93xx_spi_chip *chip = spi_get_ctldata(spi);
int value = (spi->mode & SPI_CS_HIGH) ? control : !control;
- if (espi->cs_control)
- espi->cs_control(spi, value);
+ if (chip->ops && chip->ops->cs_control)
+ chip->ops->cs_control(spi, value);
}
/**
@@ -323,12 +321,25 @@ static int ep93xx_spi_setup(struct spi_d
chip = spi_get_ctldata(spi);
if (!chip) {
+ dev_dbg(&espi->pdev->dev, "initial setup for %s\n",
+ spi->modalias);
+
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
- spi_set_ctldata(spi, chip);
chip->spi = spi;
+ chip->ops = spi->controller_data;
+
+ if (chip->ops && chip->ops->setup) {
+ ret = chip->ops->setup(spi);
+ if (ret) {
+ kfree(chip);
+ return ret;
+ }
+ }
+
+ spi_set_ctldata(spi, chip);
}
if (spi->max_speed_hz != chip->rate) {
@@ -345,7 +356,7 @@ static int ep93xx_spi_setup(struct spi_d
chip->dss = bits_per_word_to_dss(spi->bits_per_word);
- ep93xx_spi_cs_control(espi, spi, false);
+ ep93xx_spi_cs_control(spi, false);
return 0;
}
@@ -414,6 +425,8 @@ static void ep93xx_spi_cleanup(struct sp
chip = spi_get_ctldata(spi);
if (chip) {
+ if (chip->ops && chip->ops->cleanup)
+ chip->ops->cleanup(spi);
spi_set_ctldata(spi, NULL);
kfree(chip);
}
@@ -610,9 +623,9 @@ static void ep93xx_spi_process_transfer(
* chipselect briefly, we let the scheduler to handle
* any "delay" here.
*/
- ep93xx_spi_cs_control(espi, msg->spi, false);
+ ep93xx_spi_cs_control(msg->spi, false);
cond_resched();
- ep93xx_spi_cs_control(espi, msg->spi, true);
+ ep93xx_spi_cs_control(msg->spi, true);
}
}
@@ -674,7 +687,7 @@ static void ep93xx_spi_process_message(s
* the chipselect.
*/
ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi));
- ep93xx_spi_cs_control(espi, msg->spi, true);
+ ep93xx_spi_cs_control(msg->spi, true);
list_for_each_entry(t, &msg->transfers, transfer_list) {
ep93xx_spi_process_transfer(espi, msg, t);
@@ -686,7 +699,7 @@ static void ep93xx_spi_process_message(s
* Now the whole message is transferred (or failed for some reason). We
* deselect the device and disable the SPI controller.
*/
- ep93xx_spi_cs_control(espi, msg->spi, false);
+ ep93xx_spi_cs_control(msg->spi, false);
ep93xx_spi_disable(espi);
}
@@ -811,7 +824,6 @@ static int __init ep93xx_spi_probe(struc
platform_set_drvdata(pdev, master);
espi = spi_master_get_devdata(master);
- espi->cs_control = info->cs_control;
espi->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(espi->clk)) {
@@ -860,7 +872,7 @@ static int __init ep93xx_spi_probe(struc
}
error = request_irq(espi->irq, ep93xx_spi_interrupt, 0,
- "ep93xx-spi", espi);
+ "ep93xx-spi", espi);
if (error) {
dev_err(&pdev->dev, "failed to request irq\n");
goto fail_unmap_regs;
@@ -878,7 +890,7 @@ static int __init ep93xx_spi_probe(struc
/* make sure that the hardware is disabled */
ep93xx_spi_write_u8(espi, SSPCR1, 0);
- error = spi_register_master(master);
+ error = spi_register_master(master);
if (error) {
dev_err(&pdev->dev, "failed to register SPI master\n");
goto fail_free_queue;