提交 3bcbc149 编写于 作者: M Mark Brown

Merge remote-tracking branches 'spi/topic/drivers', 'spi/topic/dw',...

Merge remote-tracking branches 'spi/topic/drivers', 'spi/topic/dw', 'spi/topic/efm32', 'spi/topic/ep93xx', 'spi/topic/fsl', 'spi/topic/fsl-dspi', 'spi/topic/fsl-espi' and 'spi/topic/gpio' into spi-next
...@@ -3,24 +3,24 @@ ...@@ -3,24 +3,24 @@
Required properties: Required properties:
- #address-cells: see spi-bus.txt - #address-cells: see spi-bus.txt
- #size-cells: see spi-bus.txt - #size-cells: see spi-bus.txt
- compatible: should be "efm32,spi" - compatible: should be "energymicro,efm32-spi"
- reg: Offset and length of the register set for the controller - reg: Offset and length of the register set for the controller
- interrupts: pair specifying rx and tx irq - interrupts: pair specifying rx and tx irq
- clocks: phandle to the spi clock - clocks: phandle to the spi clock
- cs-gpios: see spi-bus.txt - cs-gpios: see spi-bus.txt
- location: Value to write to the ROUTE register's LOCATION bitfield to configure the pinmux for the device, see datasheet for values. - efm32,location: Value to write to the ROUTE register's LOCATION bitfield to configure the pinmux for the device, see datasheet for values.
Example: Example:
spi1: spi@0x4000c400 { /* USART1 */ spi1: spi@0x4000c400 { /* USART1 */
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
compatible = "efm32,spi"; compatible = "energymicro,efm32-spi";
reg = <0x4000c400 0x400>; reg = <0x4000c400 0x400>;
interrupts = <15 16>; interrupts = <15 16>;
clocks = <&cmu 20>; clocks = <&cmu 20>;
cs-gpios = <&gpio 51 1>; // D3 cs-gpios = <&gpio 51 1>; // D3
location = <1>; efm32,location = <1>;
status = "ok"; status = "ok";
ks8851@0 { ks8851@0 {
......
...@@ -10,6 +10,7 @@ Required properties: ...@@ -10,6 +10,7 @@ Required properties:
- pinctrl-names: must contain a "default" entry. - pinctrl-names: must contain a "default" entry.
- spi-num-chipselects : the number of the chipselect signals. - spi-num-chipselects : the number of the chipselect signals.
- bus-num : the slave chip chipselect signal number. - bus-num : the slave chip chipselect signal number.
- big-endian : if DSPI modudle is big endian, the bool will be set in node.
Example: Example:
dspi0@4002c000 { dspi0@4002c000 {
...@@ -24,6 +25,7 @@ dspi0@4002c000 { ...@@ -24,6 +25,7 @@ dspi0@4002c000 {
bus-num = <0>; bus-num = <0>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_dspi0_1>; pinctrl-0 = <&pinctrl_dspi0_1>;
big-endian;
status = "okay"; status = "okay";
sflash: at26df081a@0 { sflash: at26df081a@0 {
......
...@@ -270,6 +270,7 @@ config SPI_FSL_SPI ...@@ -270,6 +270,7 @@ config SPI_FSL_SPI
config SPI_FSL_DSPI config SPI_FSL_DSPI
tristate "Freescale DSPI controller" tristate "Freescale DSPI controller"
select SPI_BITBANG select SPI_BITBANG
select REGMAP_MMIO
depends on SOC_VF610 || COMPILE_TEST depends on SOC_VF610 || COMPILE_TEST
help help
This enables support for the Freescale DSPI controller in master This enables support for the Freescale DSPI controller in master
...@@ -546,7 +547,7 @@ config SPI_DW_MID_DMA ...@@ -546,7 +547,7 @@ config SPI_DW_MID_DMA
config SPI_DW_MMIO config SPI_DW_MMIO
tristate "Memory-mapped io interface driver for DW SPI core" tristate "Memory-mapped io interface driver for DW SPI core"
depends on SPI_DESIGNWARE && HAVE_CLK depends on SPI_DESIGNWARE
# #
# There are lots of SPI device types, with sensors and memory # There are lots of SPI device types, with sensors and memory
......
...@@ -66,7 +66,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) ...@@ -66,7 +66,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
dws->bus_num = 0; dws->bus_num = pdev->id;
dws->num_cs = 4; dws->num_cs = 4;
dws->max_freq = clk_get_rate(dwsmmio->clk); dws->max_freq = clk_get_rate(dwsmmio->clk);
......
...@@ -276,8 +276,7 @@ static void giveback(struct dw_spi *dws) ...@@ -276,8 +276,7 @@ static void giveback(struct dw_spi *dws)
queue_work(dws->workqueue, &dws->pump_messages); queue_work(dws->workqueue, &dws->pump_messages);
spin_unlock_irqrestore(&dws->lock, flags); spin_unlock_irqrestore(&dws->lock, flags);
last_transfer = list_entry(msg->transfers.prev, last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,
struct spi_transfer,
transfer_list); transfer_list);
if (!last_transfer->cs_change && dws->cs_control) if (!last_transfer->cs_change && dws->cs_control)
...@@ -439,12 +438,6 @@ static void pump_transfers(unsigned long data) ...@@ -439,12 +438,6 @@ static void pump_transfers(unsigned long data)
if (transfer->speed_hz != speed) { if (transfer->speed_hz != speed) {
speed = transfer->speed_hz; speed = transfer->speed_hz;
if (speed > dws->max_freq) {
printk(KERN_ERR "MRST SPI0: unsupported"
"freq: %dHz\n", speed);
message->status = -EIO;
goto early_exit;
}
/* clk_div doesn't support odd number */ /* clk_div doesn't support odd number */
clk_div = dws->max_freq / speed; clk_div = dws->max_freq / speed;
...@@ -671,12 +664,6 @@ static int dw_spi_setup(struct spi_device *spi) ...@@ -671,12 +664,6 @@ static int dw_spi_setup(struct spi_device *spi)
return 0; return 0;
} }
static void dw_spi_cleanup(struct spi_device *spi)
{
struct chip_data *chip = spi_get_ctldata(spi);
kfree(chip);
}
static int init_queue(struct dw_spi *dws) static int init_queue(struct dw_spi *dws)
{ {
INIT_LIST_HEAD(&dws->queue); INIT_LIST_HEAD(&dws->queue);
...@@ -806,9 +793,9 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -806,9 +793,9 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
master->bus_num = dws->bus_num; master->bus_num = dws->bus_num;
master->num_chipselect = dws->num_cs; master->num_chipselect = dws->num_cs;
master->cleanup = dw_spi_cleanup;
master->setup = dw_spi_setup; master->setup = dw_spi_setup;
master->transfer = dw_spi_transfer; master->transfer = dw_spi_transfer;
master->max_speed_hz = dws->max_freq;
/* Basic HW init */ /* Basic HW init */
spi_hw_init(dws); spi_hw_init(dws);
......
...@@ -287,17 +287,17 @@ static u32 efm32_spi_get_configured_location(struct efm32_spi_ddata *ddata) ...@@ -287,17 +287,17 @@ static u32 efm32_spi_get_configured_location(struct efm32_spi_ddata *ddata)
return (reg & REG_ROUTE_LOCATION__MASK) >> __ffs(REG_ROUTE_LOCATION__MASK); return (reg & REG_ROUTE_LOCATION__MASK) >> __ffs(REG_ROUTE_LOCATION__MASK);
} }
static int efm32_spi_probe_dt(struct platform_device *pdev, static void efm32_spi_probe_dt(struct platform_device *pdev,
struct spi_master *master, struct efm32_spi_ddata *ddata) struct spi_master *master, struct efm32_spi_ddata *ddata)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
u32 location; u32 location;
int ret; int ret;
if (!np) ret = of_property_read_u32(np, "efm32,location", &location);
return 1; if (ret)
/* fall back to old and (wrongly) generic property "location" */
ret = of_property_read_u32(np, "location", &location); ret = of_property_read_u32(np, "location", &location);
if (!ret) { if (!ret) {
dev_dbg(&pdev->dev, "using location %u\n", location); dev_dbg(&pdev->dev, "using location %u\n", location);
} else { } else {
...@@ -308,7 +308,6 @@ static int efm32_spi_probe_dt(struct platform_device *pdev, ...@@ -308,7 +308,6 @@ static int efm32_spi_probe_dt(struct platform_device *pdev,
} }
ddata->pdata.location = location; ddata->pdata.location = location;
return 0;
} }
static int efm32_spi_probe(struct platform_device *pdev) static int efm32_spi_probe(struct platform_device *pdev)
...@@ -318,9 +317,14 @@ static int efm32_spi_probe(struct platform_device *pdev) ...@@ -318,9 +317,14 @@ static int efm32_spi_probe(struct platform_device *pdev)
int ret; int ret;
struct spi_master *master; struct spi_master *master;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
unsigned int num_cs, i; int num_cs, i;
if (!np)
return -EINVAL;
num_cs = of_gpio_named_count(np, "cs-gpios"); num_cs = of_gpio_named_count(np, "cs-gpios");
if (num_cs < 0)
return num_cs;
master = spi_alloc_master(&pdev->dev, master = spi_alloc_master(&pdev->dev,
sizeof(*ddata) + num_cs * sizeof(unsigned)); sizeof(*ddata) + num_cs * sizeof(unsigned));
...@@ -412,23 +416,7 @@ static int efm32_spi_probe(struct platform_device *pdev) ...@@ -412,23 +416,7 @@ static int efm32_spi_probe(struct platform_device *pdev)
goto err; goto err;
} }
ret = efm32_spi_probe_dt(pdev, master, ddata); efm32_spi_probe_dt(pdev, master, ddata);
if (ret > 0) {
/* not created by device tree */
const struct efm32_spi_pdata *pdata =
dev_get_platdata(&pdev->dev);
if (pdata)
ddata->pdata = *pdata;
else
ddata->pdata.location =
efm32_spi_get_configured_location(ddata);
master->bus_num = pdev->id;
} else if (ret < 0) {
goto err_disable_clk;
}
efm32_spi_write32(ddata, 0, REG_IEN); efm32_spi_write32(ddata, 0, REG_IEN);
efm32_spi_write32(ddata, REG_ROUTE_TXPEN | REG_ROUTE_RXPEN | efm32_spi_write32(ddata, REG_ROUTE_TXPEN | REG_ROUTE_RXPEN |
...@@ -484,6 +472,9 @@ static int efm32_spi_remove(struct platform_device *pdev) ...@@ -484,6 +472,9 @@ static int efm32_spi_remove(struct platform_device *pdev)
static const struct of_device_id efm32_spi_dt_ids[] = { static const struct of_device_id efm32_spi_dt_ids[] = {
{ {
.compatible = "energymicro,efm32-spi",
}, {
/* doesn't follow the "vendor,device" scheme, don't use */
.compatible = "efm32,spi", .compatible = "efm32,spi",
}, { }, {
/* sentinel */ /* sentinel */
......
...@@ -73,8 +73,6 @@ ...@@ -73,8 +73,6 @@
* @clk: clock for the controller * @clk: clock for the controller
* @regs_base: pointer to ioremap()'d registers * @regs_base: pointer to ioremap()'d registers
* @sspdr_phys: physical address of the SSPDR register * @sspdr_phys: physical address of the SSPDR register
* @min_rate: minimum clock rate (in Hz) supported by the controller
* @max_rate: maximum clock rate (in Hz) supported by the controller
* @wait: wait here until given transfer is completed * @wait: wait here until given transfer is completed
* @current_msg: message that is currently processed (or %NULL if none) * @current_msg: message that is currently processed (or %NULL if none)
* @tx: current byte in transfer to transmit * @tx: current byte in transfer to transmit
...@@ -95,8 +93,6 @@ struct ep93xx_spi { ...@@ -95,8 +93,6 @@ struct ep93xx_spi {
struct clk *clk; struct clk *clk;
void __iomem *regs_base; void __iomem *regs_base;
unsigned long sspdr_phys; unsigned long sspdr_phys;
unsigned long min_rate;
unsigned long max_rate;
struct completion wait; struct completion wait;
struct spi_message *current_msg; struct spi_message *current_msg;
size_t tx; size_t tx;
...@@ -199,9 +195,9 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi) ...@@ -199,9 +195,9 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi)
* @div_scr: pointer to return the scr divider * @div_scr: pointer to return the scr divider
*/ */
static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
unsigned long rate, u32 rate, u8 *div_cpsr, u8 *div_scr)
u8 *div_cpsr, u8 *div_scr)
{ {
struct spi_master *master = platform_get_drvdata(espi->pdev);
unsigned long spi_clk_rate = clk_get_rate(espi->clk); unsigned long spi_clk_rate = clk_get_rate(espi->clk);
int cpsr, scr; int cpsr, scr;
...@@ -210,7 +206,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, ...@@ -210,7 +206,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
* controller. Note that minimum value is already checked in * controller. Note that minimum value is already checked in
* ep93xx_spi_transfer_one_message(). * ep93xx_spi_transfer_one_message().
*/ */
rate = clamp(rate, espi->min_rate, espi->max_rate); rate = clamp(rate, master->min_speed_hz, master->max_speed_hz);
/* /*
* Calculate divisors so that we can get speed according the * Calculate divisors so that we can get speed according the
...@@ -735,13 +731,6 @@ static int ep93xx_spi_transfer_one_message(struct spi_master *master, ...@@ -735,13 +731,6 @@ static int ep93xx_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg) struct spi_message *msg)
{ {
struct ep93xx_spi *espi = spi_master_get_devdata(master); struct ep93xx_spi *espi = spi_master_get_devdata(master);
struct spi_transfer *t;
/* first validate each transfer */
list_for_each_entry(t, &msg->transfers, transfer_list) {
if (t->speed_hz < espi->min_rate)
return -EINVAL;
}
msg->state = NULL; msg->state = NULL;
msg->status = 0; msg->status = 0;
...@@ -917,8 +906,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev) ...@@ -917,8 +906,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
* Calculate maximum and minimum supported clock rates * Calculate maximum and minimum supported clock rates
* for the controller. * for the controller.
*/ */
espi->max_rate = clk_get_rate(espi->clk) / 2; master->max_speed_hz = clk_get_rate(espi->clk) / 2;
espi->min_rate = clk_get_rate(espi->clk) / (254 * 256); master->min_speed_hz = clk_get_rate(espi->clk) / (254 * 256);
espi->pdev = pdev; espi->pdev = pdev;
espi->sspdr_phys = res->start + SSPDR; espi->sspdr_phys = res->start + SSPDR;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -108,11 +109,11 @@ struct fsl_dspi { ...@@ -108,11 +109,11 @@ struct fsl_dspi {
struct spi_bitbang bitbang; struct spi_bitbang bitbang;
struct platform_device *pdev; struct platform_device *pdev;
void __iomem *base; struct regmap *regmap;
int irq; int irq;
struct clk *clk; struct clk *clk;
struct spi_transfer *cur_transfer; struct spi_transfer *cur_transfer;
struct chip_data *cur_chip; struct chip_data *cur_chip;
size_t len; size_t len;
void *tx; void *tx;
...@@ -123,24 +124,17 @@ struct fsl_dspi { ...@@ -123,24 +124,17 @@ struct fsl_dspi {
u8 cs; u8 cs;
u16 void_write_data; u16 void_write_data;
wait_queue_head_t waitq; wait_queue_head_t waitq;
u32 waitflags; u32 waitflags;
}; };
static inline int is_double_byte_mode(struct fsl_dspi *dspi) static inline int is_double_byte_mode(struct fsl_dspi *dspi)
{ {
return ((readl(dspi->base + SPI_CTAR(dspi->cs)) & SPI_FRAME_BITS_MASK) unsigned int val;
== SPI_FRAME_BITS(8)) ? 0 : 1;
}
static void set_bit_mode(struct fsl_dspi *dspi, unsigned char bits) regmap_read(dspi->regmap, SPI_CTAR(dspi->cs), &val);
{
u32 temp;
temp = readl(dspi->base + SPI_CTAR(dspi->cs)); return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1;
temp &= ~SPI_FRAME_BITS_MASK;
temp |= SPI_FRAME_BITS(bits);
writel(temp, dspi->base + SPI_CTAR(dspi->cs));
} }
static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
...@@ -188,7 +182,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi) ...@@ -188,7 +182,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)
*/ */
if (tx_word && (dspi->len == 1)) { if (tx_word && (dspi->len == 1)) {
dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
set_bit_mode(dspi, 8); regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
tx_word = 0; tx_word = 0;
} }
...@@ -238,7 +233,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi) ...@@ -238,7 +233,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)
dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */ dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */
} }
writel(dspi_pushr, dspi->base + SPI_PUSHR); regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr);
tx_count++; tx_count++;
} }
...@@ -253,17 +249,23 @@ static int dspi_transfer_read(struct fsl_dspi *dspi) ...@@ -253,17 +249,23 @@ static int dspi_transfer_read(struct fsl_dspi *dspi)
while ((dspi->rx < dspi->rx_end) while ((dspi->rx < dspi->rx_end)
&& (rx_count < DSPI_FIFO_SIZE)) { && (rx_count < DSPI_FIFO_SIZE)) {
if (rx_word) { if (rx_word) {
unsigned int val;
if ((dspi->rx_end - dspi->rx) == 1) if ((dspi->rx_end - dspi->rx) == 1)
break; break;
d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); regmap_read(dspi->regmap, SPI_POPR, &val);
d = SPI_POPR_RXDATA(val);
if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
*(u16 *)dspi->rx = d; *(u16 *)dspi->rx = d;
dspi->rx += 2; dspi->rx += 2;
} else { } else {
d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); unsigned int val;
regmap_read(dspi->regmap, SPI_POPR, &val);
d = SPI_POPR_RXDATA(val);
if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
*(u8 *)dspi->rx = d; *(u8 *)dspi->rx = d;
dspi->rx++; dspi->rx++;
...@@ -295,13 +297,13 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -295,13 +297,13 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)
if (!dspi->tx) if (!dspi->tx)
dspi->dataflags |= TRAN_STATE_TX_VOID; dspi->dataflags |= TRAN_STATE_TX_VOID;
writel(dspi->cur_chip->mcr_val, dspi->base + SPI_MCR); regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val);
writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs)); regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val);
writel(SPI_RSER_EOQFE, dspi->base + SPI_RSER); regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE);
if (t->speed_hz) if (t->speed_hz)
writel(dspi->cur_chip->ctar_val, regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
dspi->base + SPI_CTAR(dspi->cs)); dspi->cur_chip->ctar_val);
dspi_transfer_write(dspi); dspi_transfer_write(dspi);
...@@ -315,7 +317,9 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -315,7 +317,9 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)
static void dspi_chipselect(struct spi_device *spi, int value) static void dspi_chipselect(struct spi_device *spi, int value)
{ {
struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
u32 pushr = readl(dspi->base + SPI_PUSHR); unsigned int pushr;
regmap_read(dspi->regmap, SPI_PUSHR, &pushr);
switch (value) { switch (value) {
case BITBANG_CS_ACTIVE: case BITBANG_CS_ACTIVE:
...@@ -326,7 +330,7 @@ static void dspi_chipselect(struct spi_device *spi, int value) ...@@ -326,7 +330,7 @@ static void dspi_chipselect(struct spi_device *spi, int value)
break; break;
} }
writel(pushr, dspi->base + SPI_PUSHR); regmap_write(dspi->regmap, SPI_PUSHR, pushr);
} }
static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
...@@ -338,7 +342,8 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -338,7 +342,8 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
/* Only alloc on first setup */ /* Only alloc on first setup */
chip = spi_get_ctldata(spi); chip = spi_get_ctldata(spi);
if (chip == NULL) { if (chip == NULL) {
chip = kcalloc(1, sizeof(struct chip_data), GFP_KERNEL); chip = devm_kzalloc(&spi->dev, sizeof(struct chip_data),
GFP_KERNEL);
if (!chip) if (!chip)
return -ENOMEM; return -ENOMEM;
} }
...@@ -349,7 +354,6 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -349,7 +354,6 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
fmsz = spi->bits_per_word - 1; fmsz = spi->bits_per_word - 1;
} else { } else {
pr_err("Invalid wordsize\n"); pr_err("Invalid wordsize\n");
kfree(chip);
return -ENODEV; return -ENODEV;
} }
...@@ -382,13 +386,15 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) ...@@ -382,13 +386,15 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
{ {
struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id;
writel(SPI_SR_EOQF, dspi->base + SPI_SR); regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF);
dspi_transfer_read(dspi); dspi_transfer_read(dspi);
if (!dspi->len) { if (!dspi->len) {
if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM)
set_bit_mode(dspi, 16); regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16));
dspi->waitflags = 1; dspi->waitflags = 1;
wake_up_interruptible(&dspi->waitq); wake_up_interruptible(&dspi->waitq);
} else { } else {
...@@ -430,8 +436,13 @@ static int dspi_resume(struct device *dev) ...@@ -430,8 +436,13 @@ static int dspi_resume(struct device *dev)
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops dspi_pm = { static SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume);
SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume)
static struct regmap_config dspi_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = 0x88,
}; };
static int dspi_probe(struct platform_device *pdev) static int dspi_probe(struct platform_device *pdev)
...@@ -440,6 +451,7 @@ static int dspi_probe(struct platform_device *pdev) ...@@ -440,6 +451,7 @@ static int dspi_probe(struct platform_device *pdev)
struct spi_master *master; struct spi_master *master;
struct fsl_dspi *dspi; struct fsl_dspi *dspi;
struct resource *res; struct resource *res;
void __iomem *base;
int ret = 0, cs_num, bus_num; int ret = 0, cs_num, bus_num;
master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi));
...@@ -474,12 +486,24 @@ static int dspi_probe(struct platform_device *pdev) ...@@ -474,12 +486,24 @@ static int dspi_probe(struct platform_device *pdev)
master->bus_num = bus_num; master->bus_num = bus_num;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dspi->base = devm_ioremap_resource(&pdev->dev, res); base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dspi->base)) { if (IS_ERR(base)) {
ret = PTR_ERR(dspi->base); ret = PTR_ERR(base);
goto out_master_put; goto out_master_put;
} }
dspi_regmap_config.lock_arg = dspi;
dspi_regmap_config.val_format_endian =
of_property_read_bool(np, "big-endian")
? REGMAP_ENDIAN_BIG : REGMAP_ENDIAN_DEFAULT;
dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base,
&dspi_regmap_config);
if (IS_ERR(dspi->regmap)) {
dev_err(&pdev->dev, "failed to init regmap: %ld\n",
PTR_ERR(dspi->regmap));
return PTR_ERR(dspi->regmap);
}
dspi->irq = platform_get_irq(pdev, 0); dspi->irq = platform_get_irq(pdev, 0);
if (dspi->irq < 0) { if (dspi->irq < 0) {
dev_err(&pdev->dev, "can't get platform irq\n"); dev_err(&pdev->dev, "can't get platform irq\n");
......
...@@ -219,13 +219,8 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -219,13 +219,8 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base; struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
unsigned int len = t->len; unsigned int len = t->len;
u8 bits_per_word;
int ret; int ret;
bits_per_word = spi->bits_per_word;
if (t->bits_per_word)
bits_per_word = t->bits_per_word;
mpc8xxx_spi->len = t->len; mpc8xxx_spi->len = t->len;
len = roundup(len, 4) / 4; len = roundup(len, 4) / 4;
......
...@@ -200,7 +200,7 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev) ...@@ -200,7 +200,7 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
const void *prop; const void *prop;
int ret = -ENOMEM; int ret = -ENOMEM;
pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL); pinfo = devm_kzalloc(&ofdev->dev, sizeof(*pinfo), GFP_KERNEL);
if (!pinfo) if (!pinfo)
return -ENOMEM; return -ENOMEM;
...@@ -215,15 +215,13 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev) ...@@ -215,15 +215,13 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
pdata->sysclk = get_brgfreq(); pdata->sysclk = get_brgfreq();
if (pdata->sysclk == -1) { if (pdata->sysclk == -1) {
pdata->sysclk = fsl_get_sys_freq(); pdata->sysclk = fsl_get_sys_freq();
if (pdata->sysclk == -1) { if (pdata->sysclk == -1)
ret = -ENODEV; return -ENODEV;
goto err;
}
} }
#else #else
ret = of_property_read_u32(np, "clock-frequency", &pdata->sysclk); ret = of_property_read_u32(np, "clock-frequency", &pdata->sysclk);
if (ret) if (ret)
goto err; return ret;
#endif #endif
prop = of_get_property(np, "mode", NULL); prop = of_get_property(np, "mode", NULL);
...@@ -237,8 +235,4 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev) ...@@ -237,8 +235,4 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
pdata->flags = SPI_CPM_MODE | SPI_CPM1; pdata->flags = SPI_CPM_MODE | SPI_CPM1;
return 0; return 0;
err:
kfree(pinfo);
return ret;
} }
...@@ -239,12 +239,6 @@ static int fsl_spi_setup_transfer(struct spi_device *spi, ...@@ -239,12 +239,6 @@ static int fsl_spi_setup_transfer(struct spi_device *spi,
if (!bits_per_word) if (!bits_per_word)
bits_per_word = spi->bits_per_word; bits_per_word = spi->bits_per_word;
/* Make sure its a bit width we support [4..16, 32] */
if ((bits_per_word < 4)
|| ((bits_per_word > 16) && (bits_per_word != 32))
|| (bits_per_word > mpc8xxx_spi->max_bits_per_word))
return -EINVAL;
if (!hz) if (!hz)
hz = spi->max_speed_hz; hz = spi->max_speed_hz;
...@@ -362,18 +356,28 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t, ...@@ -362,18 +356,28 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
static void fsl_spi_do_one_msg(struct spi_message *m) static void fsl_spi_do_one_msg(struct spi_message *m)
{ {
struct spi_device *spi = m->spi; struct spi_device *spi = m->spi;
struct spi_transfer *t; struct spi_transfer *t, *first;
unsigned int cs_change; unsigned int cs_change;
const int nsecs = 50; const int nsecs = 50;
int status; int status;
cs_change = 1; /* Don't allow changes if CS is active */
status = 0; first = list_first_entry(&m->transfers, struct spi_transfer,
transfer_list);
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->bits_per_word || t->speed_hz) { if ((first->bits_per_word != t->bits_per_word) ||
/* Don't allow changes if CS is active */ (first->speed_hz != t->speed_hz)) {
status = -EINVAL; status = -EINVAL;
dev_err(&spi->dev,
"bits_per_word/speed_hz should be same for the same SPI transfer\n");
return;
}
}
cs_change = 1;
status = -EINVAL;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->bits_per_word || t->speed_hz) {
if (cs_change) if (cs_change)
status = fsl_spi_setup_transfer(spi, t); status = fsl_spi_setup_transfer(spi, t);
if (status < 0) if (status < 0)
...@@ -641,6 +645,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -641,6 +645,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
if (mpc8xxx_spi->type == TYPE_GRLIB) if (mpc8xxx_spi->type == TYPE_GRLIB)
fsl_spi_grlib_probe(dev); fsl_spi_grlib_probe(dev);
master->bits_per_word_mask =
(SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32)) &
SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word);
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts; mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts;
......
...@@ -250,7 +250,7 @@ static int spi_gpio_setup(struct spi_device *spi) ...@@ -250,7 +250,7 @@ static int spi_gpio_setup(struct spi_device *spi)
/* /*
* ... otherwise, take it from spi->controller_data * ... otherwise, take it from spi->controller_data
*/ */
cs = (unsigned int) spi->controller_data; cs = (unsigned int)(uintptr_t) spi->controller_data;
} }
if (!spi->controller_state) { if (!spi->controller_state) {
......
...@@ -459,9 +459,8 @@ static void giveback(struct pl022 *pl022) ...@@ -459,9 +459,8 @@ static void giveback(struct pl022 *pl022)
struct spi_transfer *last_transfer; struct spi_transfer *last_transfer;
pl022->next_msg_cs_active = false; pl022->next_msg_cs_active = false;
last_transfer = list_entry(pl022->cur_msg->transfers.prev, last_transfer = list_last_entry(&pl022->cur_msg->transfers,
struct spi_transfer, struct spi_transfer, transfer_list);
transfer_list);
/* Delay if requested before any change in chip select */ /* Delay if requested before any change in chip select */
if (last_transfer->delay_usecs) if (last_transfer->delay_usecs)
......
...@@ -362,8 +362,7 @@ static void giveback(struct driver_data *drv_data) ...@@ -362,8 +362,7 @@ static void giveback(struct driver_data *drv_data)
drv_data->cur_msg = NULL; drv_data->cur_msg = NULL;
drv_data->cur_transfer = NULL; drv_data->cur_transfer = NULL;
last_transfer = list_entry(msg->transfers.prev, last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,
struct spi_transfer,
transfer_list); transfer_list);
/* Delay if requested before any change in chip select */ /* Delay if requested before any change in chip select */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册