diff options
35 files changed, 1920 insertions, 261 deletions
diff --git a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt index c39ac2891951..89a0084df2f7 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt +++ b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt | |||
| @@ -7,8 +7,13 @@ Required properties: | |||
| 7 | - voltage-ranges : two cells are required, first cell specifies minimum | 7 | - voltage-ranges : two cells are required, first cell specifies minimum |
| 8 | slot voltage (mV), second cell specifies maximum slot voltage (mV). | 8 | slot voltage (mV), second cell specifies maximum slot voltage (mV). |
| 9 | Several ranges could be specified. | 9 | Several ranges could be specified. |
| 10 | - gpios : (optional) may specify GPIOs in this order: Card-Detect GPIO, | 10 | |
| 11 | Optional properties: | ||
| 12 | - gpios : may specify GPIOs in this order: Card-Detect GPIO, | ||
| 11 | Write-Protect GPIO. | 13 | Write-Protect GPIO. |
| 14 | - interrupts : the interrupt of a card detect interrupt. | ||
| 15 | - interrupt-parent : the phandle for the interrupt controller that | ||
| 16 | services interrupts for this device. | ||
| 12 | 17 | ||
| 13 | Example: | 18 | Example: |
| 14 | 19 | ||
| @@ -20,4 +25,6 @@ Example: | |||
| 20 | &qe_pio_d 15 0>; | 25 | &qe_pio_d 15 0>; |
| 21 | voltage-ranges = <3300 3300>; | 26 | voltage-ranges = <3300 3300>; |
| 22 | spi-max-frequency = <50000000>; | 27 | spi-max-frequency = <50000000>; |
| 28 | interrupts = <42>; | ||
| 29 | interrupt-parent = <&PIC>; | ||
| 23 | }; | 30 | }; |
diff --git a/Documentation/devicetree/bindings/spi/spi_altera.txt b/Documentation/devicetree/bindings/spi/spi_altera.txt new file mode 100644 index 000000000000..dda375943506 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi_altera.txt | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | Altera SPI | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : should be "ALTR,spi-1.0". | ||
diff --git a/Documentation/devicetree/bindings/spi/spi_oc_tiny.txt b/Documentation/devicetree/bindings/spi/spi_oc_tiny.txt new file mode 100644 index 000000000000..d95c0b367a04 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi_oc_tiny.txt | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | OpenCores tiny SPI | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : should be "opencores,tiny-spi-rtlsvn2". | ||
| 5 | - gpios : should specify GPIOs used for chipselect. | ||
| 6 | Optional properties: | ||
| 7 | - clock-frequency : input clock frequency to the core. | ||
| 8 | - baud-width: width, in bits, of the programmable divider used to scale | ||
| 9 | the input clock to SCLK. | ||
| 10 | |||
| 11 | The clock-frequency and baud-width properties are needed only if the divider | ||
| 12 | is programmable. They are not needed if the divider is fixed. | ||
diff --git a/drivers/gpio/74x164.c b/drivers/gpio/74x164.c index d91ff4c282e9..84e070219839 100644 --- a/drivers/gpio/74x164.c +++ b/drivers/gpio/74x164.c | |||
| @@ -133,7 +133,7 @@ exit_destroy: | |||
| 133 | return ret; | 133 | return ret; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | static int gen_74x164_remove(struct spi_device *spi) | 136 | static int __devexit gen_74x164_remove(struct spi_device *spi) |
| 137 | { | 137 | { |
| 138 | struct gen_74x164_chip *chip; | 138 | struct gen_74x164_chip *chip; |
| 139 | int ret; | 139 | int ret; |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 664660e56335..b46442d7d66e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -101,7 +101,7 @@ config GPIO_VR41XX | |||
| 101 | 101 | ||
| 102 | config GPIO_SCH | 102 | config GPIO_SCH |
| 103 | tristate "Intel SCH GPIO" | 103 | tristate "Intel SCH GPIO" |
| 104 | depends on GPIOLIB && PCI | 104 | depends on GPIOLIB && PCI && X86 |
| 105 | select MFD_CORE | 105 | select MFD_CORE |
| 106 | select LPC_SCH | 106 | select LPC_SCH |
| 107 | help | 107 | help |
| @@ -321,13 +321,13 @@ config GPIO_BT8XX | |||
| 321 | 321 | ||
| 322 | config GPIO_LANGWELL | 322 | config GPIO_LANGWELL |
| 323 | bool "Intel Langwell/Penwell GPIO support" | 323 | bool "Intel Langwell/Penwell GPIO support" |
| 324 | depends on PCI | 324 | depends on PCI && X86 |
| 325 | help | 325 | help |
| 326 | Say Y here to support Intel Langwell/Penwell GPIO. | 326 | Say Y here to support Intel Langwell/Penwell GPIO. |
| 327 | 327 | ||
| 328 | config GPIO_PCH | 328 | config GPIO_PCH |
| 329 | tristate "PCH GPIO of Intel Topcliff" | 329 | tristate "PCH GPIO of Intel Topcliff" |
| 330 | depends on PCI | 330 | depends on PCI && X86 |
| 331 | help | 331 | help |
| 332 | This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff | 332 | This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff |
| 333 | which is an IOH(Input/Output Hub) for x86 embedded processor. | 333 | which is an IOH(Input/Output Hub) for x86 embedded processor. |
| @@ -368,11 +368,11 @@ config GPIO_MAX7301 | |||
| 368 | GPIO driver for Maxim MAX7301 SPI-based GPIO expander. | 368 | GPIO driver for Maxim MAX7301 SPI-based GPIO expander. |
| 369 | 369 | ||
| 370 | config GPIO_MCP23S08 | 370 | config GPIO_MCP23S08 |
| 371 | tristate "Microchip MCP23S08 I/O expander" | 371 | tristate "Microchip MCP23Sxx I/O expander" |
| 372 | depends on SPI_MASTER | 372 | depends on SPI_MASTER |
| 373 | help | 373 | help |
| 374 | SPI driver for Microchip MCP23S08 I/O expander. This provides | 374 | SPI driver for Microchip MCP23S08/MPC23S17 I/O expanders. |
| 375 | a GPIO interface supporting inputs and outputs. | 375 | This provides a GPIO interface supporting inputs and outputs. |
| 376 | 376 | ||
| 377 | config GPIO_MC33880 | 377 | config GPIO_MC33880 |
| 378 | tristate "Freescale MC33880 high-side/low-side switch" | 378 | tristate "Freescale MC33880 high-side/low-side switch" |
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index 0d05ea7d499b..6e16cba56ad2 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c | |||
| @@ -373,7 +373,7 @@ static int __devexit cs5535_gpio_remove(struct platform_device *pdev) | |||
| 373 | return 0; | 373 | return 0; |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | static struct platform_driver cs5535_gpio_drv = { | 376 | static struct platform_driver cs5535_gpio_driver = { |
| 377 | .driver = { | 377 | .driver = { |
| 378 | .name = DRV_NAME, | 378 | .name = DRV_NAME, |
| 379 | .owner = THIS_MODULE, | 379 | .owner = THIS_MODULE, |
| @@ -384,12 +384,12 @@ static struct platform_driver cs5535_gpio_drv = { | |||
| 384 | 384 | ||
| 385 | static int __init cs5535_gpio_init(void) | 385 | static int __init cs5535_gpio_init(void) |
| 386 | { | 386 | { |
| 387 | return platform_driver_register(&cs5535_gpio_drv); | 387 | return platform_driver_register(&cs5535_gpio_driver); |
| 388 | } | 388 | } |
| 389 | 389 | ||
| 390 | static void __exit cs5535_gpio_exit(void) | 390 | static void __exit cs5535_gpio_exit(void) |
| 391 | { | 391 | { |
| 392 | platform_driver_unregister(&cs5535_gpio_drv); | 392 | platform_driver_unregister(&cs5535_gpio_driver); |
| 393 | } | 393 | } |
| 394 | 394 | ||
| 395 | module_init(cs5535_gpio_init); | 395 | module_init(cs5535_gpio_init); |
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c index 54d70a47afc1..560ab648cf18 100644 --- a/drivers/gpio/langwell_gpio.c +++ b/drivers/gpio/langwell_gpio.c | |||
| @@ -187,31 +187,28 @@ MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); | |||
| 187 | 187 | ||
| 188 | static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) | 188 | static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) |
| 189 | { | 189 | { |
| 190 | struct lnw_gpio *lnw = get_irq_data(irq); | 190 | struct irq_data *data = irq_desc_get_irq_data(desc); |
| 191 | u32 base, gpio; | 191 | struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data); |
| 192 | struct irq_chip *chip = irq_data_get_irq_chip(data); | ||
| 193 | u32 base, gpio, mask; | ||
| 194 | unsigned long pending; | ||
| 192 | void __iomem *gedr; | 195 | void __iomem *gedr; |
| 193 | u32 gedr_v; | ||
| 194 | 196 | ||
| 195 | /* check GPIO controller to check which pin triggered the interrupt */ | 197 | /* check GPIO controller to check which pin triggered the interrupt */ |
| 196 | for (base = 0; base < lnw->chip.ngpio; base += 32) { | 198 | for (base = 0; base < lnw->chip.ngpio; base += 32) { |
| 197 | gedr = gpio_reg(&lnw->chip, base, GEDR); | 199 | gedr = gpio_reg(&lnw->chip, base, GEDR); |
| 198 | gedr_v = readl(gedr); | 200 | pending = readl(gedr); |
| 199 | if (!gedr_v) | 201 | while (pending) { |
| 200 | continue; | 202 | gpio = __ffs(pending) - 1; |
| 201 | for (gpio = base; gpio < base + 32; gpio++) | 203 | mask = BIT(gpio); |
| 202 | if (gedr_v & BIT(gpio % 32)) { | 204 | pending &= ~mask; |
| 203 | pr_debug("pin %d triggered\n", gpio); | 205 | /* Clear before handling so we can't lose an edge */ |
| 204 | generic_handle_irq(lnw->irq_base + gpio); | 206 | writel(mask, gedr); |
| 205 | } | 207 | generic_handle_irq(lnw->irq_base + base + gpio); |
| 206 | /* clear the edge detect status bit */ | 208 | } |
| 207 | writel(gedr_v, gedr); | ||
| 208 | } | 209 | } |
| 209 | 210 | ||
| 210 | if (desc->chip->irq_eoi) | 211 | chip->irq_eoi(data); |
| 211 | desc->chip->irq_eoi(irq_get_irq_data(irq)); | ||
| 212 | else | ||
| 213 | dev_warn(lnw->chip.dev, "missing EOI handler for irq %d\n", irq); | ||
| 214 | |||
| 215 | } | 212 | } |
| 216 | 213 | ||
| 217 | static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | 214 | static int __devinit lnw_gpio_probe(struct pci_dev *pdev, |
| @@ -279,12 +276,12 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | |||
| 279 | dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); | 276 | dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); |
| 280 | goto err5; | 277 | goto err5; |
| 281 | } | 278 | } |
| 282 | set_irq_data(pdev->irq, lnw); | 279 | irq_set_handler_data(pdev->irq, lnw); |
| 283 | set_irq_chained_handler(pdev->irq, lnw_irq_handler); | 280 | irq_set_chained_handler(pdev->irq, lnw_irq_handler); |
| 284 | for (i = 0; i < lnw->chip.ngpio; i++) { | 281 | for (i = 0; i < lnw->chip.ngpio; i++) { |
| 285 | set_irq_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip, | 282 | irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip, |
| 286 | handle_simple_irq, "demux"); | 283 | handle_simple_irq, "demux"); |
| 287 | set_irq_chip_data(i + lnw->irq_base, lnw); | 284 | irq_set_chip_data(i + lnw->irq_base, lnw); |
| 288 | } | 285 | } |
| 289 | 286 | ||
| 290 | spin_lock_init(&lnw->lock); | 287 | spin_lock_init(&lnw->lock); |
diff --git a/drivers/gpio/mc33880.c b/drivers/gpio/mc33880.c index 935479da6705..00f6d24c669d 100644 --- a/drivers/gpio/mc33880.c +++ b/drivers/gpio/mc33880.c | |||
| @@ -146,7 +146,7 @@ exit_destroy: | |||
| 146 | return ret; | 146 | return ret; |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | static int mc33880_remove(struct spi_device *spi) | 149 | static int __devexit mc33880_remove(struct spi_device *spi) |
| 150 | { | 150 | { |
| 151 | struct mc33880 *mc; | 151 | struct mc33880 *mc; |
| 152 | int ret; | 152 | int ret; |
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c index 69f6f1955a31..40e076083ec0 100644 --- a/drivers/gpio/mcp23s08.c +++ b/drivers/gpio/mcp23s08.c | |||
| @@ -10,7 +10,13 @@ | |||
| 10 | #include <linux/spi/spi.h> | 10 | #include <linux/spi/spi.h> |
| 11 | #include <linux/spi/mcp23s08.h> | 11 | #include <linux/spi/mcp23s08.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <asm/byteorder.h> | ||
| 13 | 14 | ||
| 15 | /** | ||
| 16 | * MCP types supported by driver | ||
| 17 | */ | ||
| 18 | #define MCP_TYPE_S08 0 | ||
| 19 | #define MCP_TYPE_S17 1 | ||
| 14 | 20 | ||
| 15 | /* Registers are all 8 bits wide. | 21 | /* Registers are all 8 bits wide. |
| 16 | * | 22 | * |
| @@ -35,27 +41,38 @@ | |||
| 35 | #define MCP_GPIO 0x09 | 41 | #define MCP_GPIO 0x09 |
| 36 | #define MCP_OLAT 0x0a | 42 | #define MCP_OLAT 0x0a |
| 37 | 43 | ||
| 44 | struct mcp23s08; | ||
| 45 | |||
| 46 | struct mcp23s08_ops { | ||
| 47 | int (*read)(struct mcp23s08 *mcp, unsigned reg); | ||
| 48 | int (*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val); | ||
| 49 | int (*read_regs)(struct mcp23s08 *mcp, unsigned reg, | ||
| 50 | u16 *vals, unsigned n); | ||
| 51 | }; | ||
| 52 | |||
| 38 | struct mcp23s08 { | 53 | struct mcp23s08 { |
| 39 | struct spi_device *spi; | 54 | struct spi_device *spi; |
| 40 | u8 addr; | 55 | u8 addr; |
| 41 | 56 | ||
| 42 | u8 cache[11]; | 57 | u16 cache[11]; |
| 43 | /* lock protects the cached values */ | 58 | /* lock protects the cached values */ |
| 44 | struct mutex lock; | 59 | struct mutex lock; |
| 45 | 60 | ||
| 46 | struct gpio_chip chip; | 61 | struct gpio_chip chip; |
| 47 | 62 | ||
| 48 | struct work_struct work; | 63 | struct work_struct work; |
| 64 | |||
| 65 | const struct mcp23s08_ops *ops; | ||
| 49 | }; | 66 | }; |
| 50 | 67 | ||
| 51 | /* A given spi_device can represent up to four mcp23s08 chips | 68 | /* A given spi_device can represent up to eight mcp23sxx chips |
| 52 | * sharing the same chipselect but using different addresses | 69 | * sharing the same chipselect but using different addresses |
| 53 | * (e.g. chips #0 and #3 might be populated, but not #1 or $2). | 70 | * (e.g. chips #0 and #3 might be populated, but not #1 or $2). |
| 54 | * Driver data holds all the per-chip data. | 71 | * Driver data holds all the per-chip data. |
| 55 | */ | 72 | */ |
| 56 | struct mcp23s08_driver_data { | 73 | struct mcp23s08_driver_data { |
| 57 | unsigned ngpio; | 74 | unsigned ngpio; |
| 58 | struct mcp23s08 *mcp[4]; | 75 | struct mcp23s08 *mcp[8]; |
| 59 | struct mcp23s08 chip[]; | 76 | struct mcp23s08 chip[]; |
| 60 | }; | 77 | }; |
| 61 | 78 | ||
| @@ -70,7 +87,7 @@ static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) | |||
| 70 | return (status < 0) ? status : rx[0]; | 87 | return (status < 0) ? status : rx[0]; |
| 71 | } | 88 | } |
| 72 | 89 | ||
| 73 | static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, u8 val) | 90 | static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) |
| 74 | { | 91 | { |
| 75 | u8 tx[3]; | 92 | u8 tx[3]; |
| 76 | 93 | ||
| @@ -81,17 +98,81 @@ static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, u8 val) | |||
| 81 | } | 98 | } |
| 82 | 99 | ||
| 83 | static int | 100 | static int |
| 84 | mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u8 *vals, unsigned n) | 101 | mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) |
| 85 | { | 102 | { |
| 86 | u8 tx[2]; | 103 | u8 tx[2], *tmp; |
| 104 | int status; | ||
| 87 | 105 | ||
| 88 | if ((n + reg) > sizeof mcp->cache) | 106 | if ((n + reg) > sizeof mcp->cache) |
| 89 | return -EINVAL; | 107 | return -EINVAL; |
| 90 | tx[0] = mcp->addr | 0x01; | 108 | tx[0] = mcp->addr | 0x01; |
| 91 | tx[1] = reg; | 109 | tx[1] = reg; |
| 92 | return spi_write_then_read(mcp->spi, tx, sizeof tx, vals, n); | 110 | |
| 111 | tmp = (u8 *)vals; | ||
| 112 | status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n); | ||
| 113 | if (status >= 0) { | ||
| 114 | while (n--) | ||
| 115 | vals[n] = tmp[n]; /* expand to 16bit */ | ||
| 116 | } | ||
| 117 | return status; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg) | ||
| 121 | { | ||
| 122 | u8 tx[2], rx[2]; | ||
| 123 | int status; | ||
| 124 | |||
| 125 | tx[0] = mcp->addr | 0x01; | ||
| 126 | tx[1] = reg << 1; | ||
| 127 | status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx); | ||
| 128 | return (status < 0) ? status : (rx[0] | (rx[1] << 8)); | ||
| 129 | } | ||
| 130 | |||
| 131 | static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) | ||
| 132 | { | ||
| 133 | u8 tx[4]; | ||
| 134 | |||
| 135 | tx[0] = mcp->addr; | ||
| 136 | tx[1] = reg << 1; | ||
| 137 | tx[2] = val; | ||
| 138 | tx[3] = val >> 8; | ||
| 139 | return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0); | ||
| 140 | } | ||
| 141 | |||
| 142 | static int | ||
| 143 | mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) | ||
| 144 | { | ||
| 145 | u8 tx[2]; | ||
| 146 | int status; | ||
| 147 | |||
| 148 | if ((n + reg) > sizeof mcp->cache) | ||
| 149 | return -EINVAL; | ||
| 150 | tx[0] = mcp->addr | 0x01; | ||
| 151 | tx[1] = reg << 1; | ||
| 152 | |||
| 153 | status = spi_write_then_read(mcp->spi, tx, sizeof tx, | ||
| 154 | (u8 *)vals, n * 2); | ||
| 155 | if (status >= 0) { | ||
| 156 | while (n--) | ||
| 157 | vals[n] = __le16_to_cpu((__le16)vals[n]); | ||
| 158 | } | ||
| 159 | |||
| 160 | return status; | ||
| 93 | } | 161 | } |
| 94 | 162 | ||
| 163 | static const struct mcp23s08_ops mcp23s08_ops = { | ||
| 164 | .read = mcp23s08_read, | ||
| 165 | .write = mcp23s08_write, | ||
| 166 | .read_regs = mcp23s08_read_regs, | ||
| 167 | }; | ||
| 168 | |||
| 169 | static const struct mcp23s08_ops mcp23s17_ops = { | ||
| 170 | .read = mcp23s17_read, | ||
| 171 | .write = mcp23s17_write, | ||
| 172 | .read_regs = mcp23s17_read_regs, | ||
| 173 | }; | ||
| 174 | |||
| 175 | |||
| 95 | /*----------------------------------------------------------------------*/ | 176 | /*----------------------------------------------------------------------*/ |
| 96 | 177 | ||
| 97 | static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset) | 178 | static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset) |
| @@ -101,7 +182,7 @@ static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset) | |||
| 101 | 182 | ||
| 102 | mutex_lock(&mcp->lock); | 183 | mutex_lock(&mcp->lock); |
| 103 | mcp->cache[MCP_IODIR] |= (1 << offset); | 184 | mcp->cache[MCP_IODIR] |= (1 << offset); |
| 104 | status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]); | 185 | status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]); |
| 105 | mutex_unlock(&mcp->lock); | 186 | mutex_unlock(&mcp->lock); |
| 106 | return status; | 187 | return status; |
| 107 | } | 188 | } |
| @@ -114,7 +195,7 @@ static int mcp23s08_get(struct gpio_chip *chip, unsigned offset) | |||
| 114 | mutex_lock(&mcp->lock); | 195 | mutex_lock(&mcp->lock); |
| 115 | 196 | ||
| 116 | /* REVISIT reading this clears any IRQ ... */ | 197 | /* REVISIT reading this clears any IRQ ... */ |
| 117 | status = mcp23s08_read(mcp, MCP_GPIO); | 198 | status = mcp->ops->read(mcp, MCP_GPIO); |
| 118 | if (status < 0) | 199 | if (status < 0) |
| 119 | status = 0; | 200 | status = 0; |
| 120 | else { | 201 | else { |
| @@ -127,20 +208,20 @@ static int mcp23s08_get(struct gpio_chip *chip, unsigned offset) | |||
| 127 | 208 | ||
| 128 | static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value) | 209 | static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value) |
| 129 | { | 210 | { |
| 130 | u8 olat = mcp->cache[MCP_OLAT]; | 211 | unsigned olat = mcp->cache[MCP_OLAT]; |
| 131 | 212 | ||
| 132 | if (value) | 213 | if (value) |
| 133 | olat |= mask; | 214 | olat |= mask; |
| 134 | else | 215 | else |
| 135 | olat &= ~mask; | 216 | olat &= ~mask; |
| 136 | mcp->cache[MCP_OLAT] = olat; | 217 | mcp->cache[MCP_OLAT] = olat; |
| 137 | return mcp23s08_write(mcp, MCP_OLAT, olat); | 218 | return mcp->ops->write(mcp, MCP_OLAT, olat); |
| 138 | } | 219 | } |
| 139 | 220 | ||
| 140 | static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value) | 221 | static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value) |
| 141 | { | 222 | { |
| 142 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); | 223 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); |
| 143 | u8 mask = 1 << offset; | 224 | unsigned mask = 1 << offset; |
| 144 | 225 | ||
| 145 | mutex_lock(&mcp->lock); | 226 | mutex_lock(&mcp->lock); |
| 146 | __mcp23s08_set(mcp, mask, value); | 227 | __mcp23s08_set(mcp, mask, value); |
| @@ -151,14 +232,14 @@ static int | |||
| 151 | mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value) | 232 | mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value) |
| 152 | { | 233 | { |
| 153 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); | 234 | struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); |
| 154 | u8 mask = 1 << offset; | 235 | unsigned mask = 1 << offset; |
| 155 | int status; | 236 | int status; |
| 156 | 237 | ||
| 157 | mutex_lock(&mcp->lock); | 238 | mutex_lock(&mcp->lock); |
| 158 | status = __mcp23s08_set(mcp, mask, value); | 239 | status = __mcp23s08_set(mcp, mask, value); |
| 159 | if (status == 0) { | 240 | if (status == 0) { |
| 160 | mcp->cache[MCP_IODIR] &= ~mask; | 241 | mcp->cache[MCP_IODIR] &= ~mask; |
| 161 | status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]); | 242 | status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]); |
| 162 | } | 243 | } |
| 163 | mutex_unlock(&mcp->lock); | 244 | mutex_unlock(&mcp->lock); |
| 164 | return status; | 245 | return status; |
| @@ -184,16 +265,16 @@ static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
| 184 | mcp = container_of(chip, struct mcp23s08, chip); | 265 | mcp = container_of(chip, struct mcp23s08, chip); |
| 185 | 266 | ||
| 186 | /* NOTE: we only handle one bank for now ... */ | 267 | /* NOTE: we only handle one bank for now ... */ |
| 187 | bank = '0' + ((mcp->addr >> 1) & 0x3); | 268 | bank = '0' + ((mcp->addr >> 1) & 0x7); |
| 188 | 269 | ||
| 189 | mutex_lock(&mcp->lock); | 270 | mutex_lock(&mcp->lock); |
| 190 | t = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache); | 271 | t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache)); |
| 191 | if (t < 0) { | 272 | if (t < 0) { |
| 192 | seq_printf(s, " I/O ERROR %d\n", t); | 273 | seq_printf(s, " I/O ERROR %d\n", t); |
| 193 | goto done; | 274 | goto done; |
| 194 | } | 275 | } |
| 195 | 276 | ||
| 196 | for (t = 0, mask = 1; t < 8; t++, mask <<= 1) { | 277 | for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) { |
| 197 | const char *label; | 278 | const char *label; |
| 198 | 279 | ||
| 199 | label = gpiochip_is_requested(chip, t); | 280 | label = gpiochip_is_requested(chip, t); |
| @@ -219,28 +300,33 @@ done: | |||
| 219 | /*----------------------------------------------------------------------*/ | 300 | /*----------------------------------------------------------------------*/ |
| 220 | 301 | ||
| 221 | static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, | 302 | static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, |
| 222 | unsigned base, unsigned pullups) | 303 | unsigned type, unsigned base, unsigned pullups) |
| 223 | { | 304 | { |
| 224 | struct mcp23s08_driver_data *data = spi_get_drvdata(spi); | 305 | struct mcp23s08_driver_data *data = spi_get_drvdata(spi); |
| 225 | struct mcp23s08 *mcp = data->mcp[addr]; | 306 | struct mcp23s08 *mcp = data->mcp[addr]; |
| 226 | int status; | 307 | int status; |
| 227 | int do_update = 0; | ||
| 228 | 308 | ||
| 229 | mutex_init(&mcp->lock); | 309 | mutex_init(&mcp->lock); |
| 230 | 310 | ||
| 231 | mcp->spi = spi; | 311 | mcp->spi = spi; |
| 232 | mcp->addr = 0x40 | (addr << 1); | 312 | mcp->addr = 0x40 | (addr << 1); |
| 233 | 313 | ||
| 234 | mcp->chip.label = "mcp23s08", | ||
| 235 | |||
| 236 | mcp->chip.direction_input = mcp23s08_direction_input; | 314 | mcp->chip.direction_input = mcp23s08_direction_input; |
| 237 | mcp->chip.get = mcp23s08_get; | 315 | mcp->chip.get = mcp23s08_get; |
| 238 | mcp->chip.direction_output = mcp23s08_direction_output; | 316 | mcp->chip.direction_output = mcp23s08_direction_output; |
| 239 | mcp->chip.set = mcp23s08_set; | 317 | mcp->chip.set = mcp23s08_set; |
| 240 | mcp->chip.dbg_show = mcp23s08_dbg_show; | 318 | mcp->chip.dbg_show = mcp23s08_dbg_show; |
| 241 | 319 | ||
| 320 | if (type == MCP_TYPE_S17) { | ||
| 321 | mcp->ops = &mcp23s17_ops; | ||
| 322 | mcp->chip.ngpio = 16; | ||
| 323 | mcp->chip.label = "mcp23s17"; | ||
| 324 | } else { | ||
| 325 | mcp->ops = &mcp23s08_ops; | ||
| 326 | mcp->chip.ngpio = 8; | ||
| 327 | mcp->chip.label = "mcp23s08"; | ||
| 328 | } | ||
| 242 | mcp->chip.base = base; | 329 | mcp->chip.base = base; |
| 243 | mcp->chip.ngpio = 8; | ||
| 244 | mcp->chip.can_sleep = 1; | 330 | mcp->chip.can_sleep = 1; |
| 245 | mcp->chip.dev = &spi->dev; | 331 | mcp->chip.dev = &spi->dev; |
| 246 | mcp->chip.owner = THIS_MODULE; | 332 | mcp->chip.owner = THIS_MODULE; |
| @@ -248,45 +334,39 @@ static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, | |||
| 248 | /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, | 334 | /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, |
| 249 | * and MCP_IOCON.HAEN = 1, so we work with all chips. | 335 | * and MCP_IOCON.HAEN = 1, so we work with all chips. |
| 250 | */ | 336 | */ |
| 251 | status = mcp23s08_read(mcp, MCP_IOCON); | 337 | status = mcp->ops->read(mcp, MCP_IOCON); |
| 252 | if (status < 0) | 338 | if (status < 0) |
| 253 | goto fail; | 339 | goto fail; |
| 254 | if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) { | 340 | if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) { |
| 255 | status &= ~IOCON_SEQOP; | 341 | /* mcp23s17 has IOCON twice, make sure they are in sync */ |
| 256 | status |= IOCON_HAEN; | 342 | status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); |
| 257 | status = mcp23s08_write(mcp, MCP_IOCON, (u8) status); | 343 | status |= IOCON_HAEN | (IOCON_HAEN << 8); |
| 344 | status = mcp->ops->write(mcp, MCP_IOCON, status); | ||
| 258 | if (status < 0) | 345 | if (status < 0) |
| 259 | goto fail; | 346 | goto fail; |
| 260 | } | 347 | } |
| 261 | 348 | ||
| 262 | /* configure ~100K pullups */ | 349 | /* configure ~100K pullups */ |
| 263 | status = mcp23s08_write(mcp, MCP_GPPU, pullups); | 350 | status = mcp->ops->write(mcp, MCP_GPPU, pullups); |
| 264 | if (status < 0) | 351 | if (status < 0) |
| 265 | goto fail; | 352 | goto fail; |
| 266 | 353 | ||
| 267 | status = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache); | 354 | status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache)); |
| 268 | if (status < 0) | 355 | if (status < 0) |
| 269 | goto fail; | 356 | goto fail; |
| 270 | 357 | ||
| 271 | /* disable inverter on input */ | 358 | /* disable inverter on input */ |
| 272 | if (mcp->cache[MCP_IPOL] != 0) { | 359 | if (mcp->cache[MCP_IPOL] != 0) { |
| 273 | mcp->cache[MCP_IPOL] = 0; | 360 | mcp->cache[MCP_IPOL] = 0; |
| 274 | do_update = 1; | 361 | status = mcp->ops->write(mcp, MCP_IPOL, 0); |
| 362 | if (status < 0) | ||
| 363 | goto fail; | ||
| 275 | } | 364 | } |
| 276 | 365 | ||
| 277 | /* disable irqs */ | 366 | /* disable irqs */ |
| 278 | if (mcp->cache[MCP_GPINTEN] != 0) { | 367 | if (mcp->cache[MCP_GPINTEN] != 0) { |
| 279 | mcp->cache[MCP_GPINTEN] = 0; | 368 | mcp->cache[MCP_GPINTEN] = 0; |
| 280 | do_update = 1; | 369 | status = mcp->ops->write(mcp, MCP_GPINTEN, 0); |
| 281 | } | ||
| 282 | |||
| 283 | if (do_update) { | ||
| 284 | u8 tx[4]; | ||
| 285 | |||
| 286 | tx[0] = mcp->addr; | ||
| 287 | tx[1] = MCP_IPOL; | ||
| 288 | memcpy(&tx[2], &mcp->cache[MCP_IPOL], sizeof(tx) - 2); | ||
| 289 | status = spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0); | ||
| 290 | if (status < 0) | 370 | if (status < 0) |
| 291 | goto fail; | 371 | goto fail; |
| 292 | } | 372 | } |
| @@ -305,19 +385,26 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
| 305 | unsigned addr; | 385 | unsigned addr; |
| 306 | unsigned chips = 0; | 386 | unsigned chips = 0; |
| 307 | struct mcp23s08_driver_data *data; | 387 | struct mcp23s08_driver_data *data; |
| 308 | int status; | 388 | int status, type; |
| 309 | unsigned base; | 389 | unsigned base; |
| 310 | 390 | ||
| 391 | type = spi_get_device_id(spi)->driver_data; | ||
| 392 | |||
| 311 | pdata = spi->dev.platform_data; | 393 | pdata = spi->dev.platform_data; |
| 312 | if (!pdata || !gpio_is_valid(pdata->base)) { | 394 | if (!pdata || !gpio_is_valid(pdata->base)) { |
| 313 | dev_dbg(&spi->dev, "invalid or missing platform data\n"); | 395 | dev_dbg(&spi->dev, "invalid or missing platform data\n"); |
| 314 | return -EINVAL; | 396 | return -EINVAL; |
| 315 | } | 397 | } |
| 316 | 398 | ||
| 317 | for (addr = 0; addr < 4; addr++) { | 399 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { |
| 318 | if (!pdata->chip[addr].is_present) | 400 | if (!pdata->chip[addr].is_present) |
| 319 | continue; | 401 | continue; |
| 320 | chips++; | 402 | chips++; |
| 403 | if ((type == MCP_TYPE_S08) && (addr > 3)) { | ||
| 404 | dev_err(&spi->dev, | ||
| 405 | "mcp23s08 only supports address 0..3\n"); | ||
| 406 | return -EINVAL; | ||
| 407 | } | ||
| 321 | } | 408 | } |
| 322 | if (!chips) | 409 | if (!chips) |
| 323 | return -ENODEV; | 410 | return -ENODEV; |
| @@ -329,16 +416,17 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
| 329 | spi_set_drvdata(spi, data); | 416 | spi_set_drvdata(spi, data); |
| 330 | 417 | ||
| 331 | base = pdata->base; | 418 | base = pdata->base; |
| 332 | for (addr = 0; addr < 4; addr++) { | 419 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { |
| 333 | if (!pdata->chip[addr].is_present) | 420 | if (!pdata->chip[addr].is_present) |
| 334 | continue; | 421 | continue; |
| 335 | chips--; | 422 | chips--; |
| 336 | data->mcp[addr] = &data->chip[chips]; | 423 | data->mcp[addr] = &data->chip[chips]; |
| 337 | status = mcp23s08_probe_one(spi, addr, base, | 424 | status = mcp23s08_probe_one(spi, addr, type, base, |
| 338 | pdata->chip[addr].pullups); | 425 | pdata->chip[addr].pullups); |
| 339 | if (status < 0) | 426 | if (status < 0) |
| 340 | goto fail; | 427 | goto fail; |
| 341 | base += 8; | 428 | |
| 429 | base += (type == MCP_TYPE_S17) ? 16 : 8; | ||
| 342 | } | 430 | } |
| 343 | data->ngpio = base - pdata->base; | 431 | data->ngpio = base - pdata->base; |
| 344 | 432 | ||
| @@ -358,7 +446,7 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
| 358 | return 0; | 446 | return 0; |
| 359 | 447 | ||
| 360 | fail: | 448 | fail: |
| 361 | for (addr = 0; addr < 4; addr++) { | 449 | for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) { |
| 362 | int tmp; | 450 | int tmp; |
| 363 | 451 | ||
| 364 | if (!data->mcp[addr]) | 452 | if (!data->mcp[addr]) |
| @@ -388,7 +476,7 @@ static int mcp23s08_remove(struct spi_device *spi) | |||
| 388 | } | 476 | } |
| 389 | } | 477 | } |
| 390 | 478 | ||
| 391 | for (addr = 0; addr < 4; addr++) { | 479 | for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) { |
| 392 | int tmp; | 480 | int tmp; |
| 393 | 481 | ||
| 394 | if (!data->mcp[addr]) | 482 | if (!data->mcp[addr]) |
| @@ -405,9 +493,17 @@ static int mcp23s08_remove(struct spi_device *spi) | |||
| 405 | return status; | 493 | return status; |
| 406 | } | 494 | } |
| 407 | 495 | ||
| 496 | static const struct spi_device_id mcp23s08_ids[] = { | ||
| 497 | { "mcp23s08", MCP_TYPE_S08 }, | ||
| 498 | { "mcp23s17", MCP_TYPE_S17 }, | ||
| 499 | { }, | ||
| 500 | }; | ||
| 501 | MODULE_DEVICE_TABLE(spi, mcp23s08_ids); | ||
| 502 | |||
| 408 | static struct spi_driver mcp23s08_driver = { | 503 | static struct spi_driver mcp23s08_driver = { |
| 409 | .probe = mcp23s08_probe, | 504 | .probe = mcp23s08_probe, |
| 410 | .remove = mcp23s08_remove, | 505 | .remove = mcp23s08_remove, |
| 506 | .id_table = mcp23s08_ids, | ||
| 411 | .driver = { | 507 | .driver = { |
| 412 | .name = "mcp23s08", | 508 | .name = "mcp23s08", |
| 413 | .owner = THIS_MODULE, | 509 | .owner = THIS_MODULE, |
| @@ -432,4 +528,3 @@ static void __exit mcp23s08_exit(void) | |||
| 432 | module_exit(mcp23s08_exit); | 528 | module_exit(mcp23s08_exit); |
| 433 | 529 | ||
| 434 | MODULE_LICENSE("GPL"); | 530 | MODULE_LICENSE("GPL"); |
| 435 | MODULE_ALIAS("spi:mcp23s08"); | ||
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index b473429eee75..2fc25dec7cf5 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c | |||
| @@ -462,7 +462,8 @@ pca953x_get_alt_pdata(struct i2c_client *client) | |||
| 462 | { | 462 | { |
| 463 | struct pca953x_platform_data *pdata; | 463 | struct pca953x_platform_data *pdata; |
| 464 | struct device_node *node; | 464 | struct device_node *node; |
| 465 | const uint16_t *val; | 465 | const __be32 *val; |
| 466 | int size; | ||
| 466 | 467 | ||
| 467 | node = client->dev.of_node; | 468 | node = client->dev.of_node; |
| 468 | if (node == NULL) | 469 | if (node == NULL) |
| @@ -475,13 +476,13 @@ pca953x_get_alt_pdata(struct i2c_client *client) | |||
| 475 | } | 476 | } |
| 476 | 477 | ||
| 477 | pdata->gpio_base = -1; | 478 | pdata->gpio_base = -1; |
| 478 | val = of_get_property(node, "linux,gpio-base", NULL); | 479 | val = of_get_property(node, "linux,gpio-base", &size); |
| 479 | if (val) { | 480 | if (val) { |
| 480 | if (*val < 0) | 481 | if (size != sizeof(*val)) |
| 481 | dev_warn(&client->dev, | 482 | dev_warn(&client->dev, "%s: wrong linux,gpio-base\n", |
| 482 | "invalid gpio-base in device tree\n"); | 483 | node->full_name); |
| 483 | else | 484 | else |
| 484 | pdata->gpio_base = *val; | 485 | pdata->gpio_base = be32_to_cpup(val); |
| 485 | } | 486 | } |
| 486 | 487 | ||
| 487 | val = of_get_property(node, "polarity", NULL); | 488 | val = of_get_property(node, "polarity", NULL); |
diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/sx150x.c index e60be0015c9b..d2f874c3d3d5 100644 --- a/drivers/gpio/sx150x.c +++ b/drivers/gpio/sx150x.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
| 26 | #include <linux/i2c/sx150x.h> | 26 | #include <linux/i2c/sx150x.h> |
| 27 | 27 | ||
| 28 | #define NO_UPDATE_PENDING -1 | ||
| 29 | |||
| 28 | struct sx150x_device_data { | 30 | struct sx150x_device_data { |
| 29 | u8 reg_pullup; | 31 | u8 reg_pullup; |
| 30 | u8 reg_pulldn; | 32 | u8 reg_pulldn; |
| @@ -47,8 +49,11 @@ struct sx150x_chip { | |||
| 47 | const struct sx150x_device_data *dev_cfg; | 49 | const struct sx150x_device_data *dev_cfg; |
| 48 | int irq_summary; | 50 | int irq_summary; |
| 49 | int irq_base; | 51 | int irq_base; |
| 52 | int irq_update; | ||
| 50 | u32 irq_sense; | 53 | u32 irq_sense; |
| 51 | unsigned long irq_set_type_pending; | 54 | u32 irq_masked; |
| 55 | u32 dev_sense; | ||
| 56 | u32 dev_masked; | ||
| 52 | struct irq_chip irq_chip; | 57 | struct irq_chip irq_chip; |
| 53 | struct mutex lock; | 58 | struct mutex lock; |
| 54 | }; | 59 | }; |
| @@ -312,9 +317,8 @@ static void sx150x_irq_mask(struct irq_data *d) | |||
| 312 | 317 | ||
| 313 | chip = container_of(ic, struct sx150x_chip, irq_chip); | 318 | chip = container_of(ic, struct sx150x_chip, irq_chip); |
| 314 | n = d->irq - chip->irq_base; | 319 | n = d->irq - chip->irq_base; |
| 315 | 320 | chip->irq_masked |= (1 << n); | |
| 316 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1); | 321 | chip->irq_update = n; |
| 317 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0); | ||
| 318 | } | 322 | } |
| 319 | 323 | ||
| 320 | static void sx150x_irq_unmask(struct irq_data *d) | 324 | static void sx150x_irq_unmask(struct irq_data *d) |
| @@ -326,9 +330,8 @@ static void sx150x_irq_unmask(struct irq_data *d) | |||
| 326 | chip = container_of(ic, struct sx150x_chip, irq_chip); | 330 | chip = container_of(ic, struct sx150x_chip, irq_chip); |
| 327 | n = d->irq - chip->irq_base; | 331 | n = d->irq - chip->irq_base; |
| 328 | 332 | ||
| 329 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0); | 333 | chip->irq_masked &= ~(1 << n); |
| 330 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, | 334 | chip->irq_update = n; |
| 331 | chip->irq_sense >> (n * 2)); | ||
| 332 | } | 335 | } |
| 333 | 336 | ||
| 334 | static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) | 337 | static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) |
| @@ -350,7 +353,7 @@ static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) | |||
| 350 | 353 | ||
| 351 | chip->irq_sense &= ~(3UL << (n * 2)); | 354 | chip->irq_sense &= ~(3UL << (n * 2)); |
| 352 | chip->irq_sense |= val << (n * 2); | 355 | chip->irq_sense |= val << (n * 2); |
| 353 | chip->irq_set_type_pending |= BIT(n); | 356 | chip->irq_update = n; |
| 354 | return 0; | 357 | return 0; |
| 355 | } | 358 | } |
| 356 | 359 | ||
| @@ -404,15 +407,29 @@ static void sx150x_irq_bus_sync_unlock(struct irq_data *d) | |||
| 404 | 407 | ||
| 405 | chip = container_of(ic, struct sx150x_chip, irq_chip); | 408 | chip = container_of(ic, struct sx150x_chip, irq_chip); |
| 406 | 409 | ||
| 407 | while (chip->irq_set_type_pending) { | 410 | if (chip->irq_update == NO_UPDATE_PENDING) |
| 408 | n = __ffs(chip->irq_set_type_pending); | 411 | goto out; |
| 409 | chip->irq_set_type_pending &= ~BIT(n); | 412 | |
| 410 | if (!(irq_to_desc(n + chip->irq_base)->status & IRQ_MASKED)) | 413 | n = chip->irq_update; |
| 411 | sx150x_write_cfg(chip, n, 2, | 414 | chip->irq_update = NO_UPDATE_PENDING; |
| 412 | chip->dev_cfg->reg_sense, | ||
| 413 | chip->irq_sense >> (n * 2)); | ||
| 414 | } | ||
| 415 | 415 | ||
| 416 | /* Avoid updates if nothing changed */ | ||
| 417 | if (chip->dev_sense == chip->irq_sense && | ||
| 418 | chip->dev_sense == chip->irq_masked) | ||
| 419 | goto out; | ||
| 420 | |||
| 421 | chip->dev_sense = chip->irq_sense; | ||
| 422 | chip->dev_masked = chip->irq_masked; | ||
| 423 | |||
| 424 | if (chip->irq_masked & (1 << n)) { | ||
| 425 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1); | ||
| 426 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0); | ||
| 427 | } else { | ||
| 428 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0); | ||
| 429 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, | ||
| 430 | chip->irq_sense >> (n * 2)); | ||
| 431 | } | ||
| 432 | out: | ||
| 416 | mutex_unlock(&chip->lock); | 433 | mutex_unlock(&chip->lock); |
| 417 | } | 434 | } |
| 418 | 435 | ||
| @@ -445,8 +462,11 @@ static void sx150x_init_chip(struct sx150x_chip *chip, | |||
| 445 | chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock; | 462 | chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock; |
| 446 | chip->irq_summary = -1; | 463 | chip->irq_summary = -1; |
| 447 | chip->irq_base = -1; | 464 | chip->irq_base = -1; |
| 465 | chip->irq_masked = ~0; | ||
| 448 | chip->irq_sense = 0; | 466 | chip->irq_sense = 0; |
| 449 | chip->irq_set_type_pending = 0; | 467 | chip->dev_masked = ~0; |
| 468 | chip->dev_sense = 0; | ||
| 469 | chip->irq_update = NO_UPDATE_PENDING; | ||
| 450 | } | 470 | } |
| 451 | 471 | ||
| 452 | static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) | 472 | static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) |
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index 1247e5de9faa..5530def54e5b 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c | |||
| @@ -34,6 +34,7 @@ enum { | |||
| 34 | struct of_mmc_spi { | 34 | struct of_mmc_spi { |
| 35 | int gpios[NUM_GPIOS]; | 35 | int gpios[NUM_GPIOS]; |
| 36 | bool alow_gpios[NUM_GPIOS]; | 36 | bool alow_gpios[NUM_GPIOS]; |
| 37 | int detect_irq; | ||
| 37 | struct mmc_spi_platform_data pdata; | 38 | struct mmc_spi_platform_data pdata; |
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| @@ -61,6 +62,22 @@ static int of_mmc_spi_get_ro(struct device *dev) | |||
| 61 | return of_mmc_spi_read_gpio(dev, WP_GPIO); | 62 | return of_mmc_spi_read_gpio(dev, WP_GPIO); |
| 62 | } | 63 | } |
| 63 | 64 | ||
| 65 | static int of_mmc_spi_init(struct device *dev, | ||
| 66 | irqreturn_t (*irqhandler)(int, void *), void *mmc) | ||
| 67 | { | ||
| 68 | struct of_mmc_spi *oms = to_of_mmc_spi(dev); | ||
| 69 | |||
| 70 | return request_threaded_irq(oms->detect_irq, NULL, irqhandler, 0, | ||
| 71 | dev_name(dev), mmc); | ||
| 72 | } | ||
| 73 | |||
| 74 | static void of_mmc_spi_exit(struct device *dev, void *mmc) | ||
| 75 | { | ||
| 76 | struct of_mmc_spi *oms = to_of_mmc_spi(dev); | ||
| 77 | |||
| 78 | free_irq(oms->detect_irq, mmc); | ||
| 79 | } | ||
| 80 | |||
| 64 | struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) | 81 | struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) |
| 65 | { | 82 | { |
| 66 | struct device *dev = &spi->dev; | 83 | struct device *dev = &spi->dev; |
| @@ -121,8 +138,13 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) | |||
| 121 | if (gpio_is_valid(oms->gpios[WP_GPIO])) | 138 | if (gpio_is_valid(oms->gpios[WP_GPIO])) |
| 122 | oms->pdata.get_ro = of_mmc_spi_get_ro; | 139 | oms->pdata.get_ro = of_mmc_spi_get_ro; |
| 123 | 140 | ||
| 124 | /* We don't support interrupts yet, let's poll. */ | 141 | oms->detect_irq = irq_of_parse_and_map(np, 0); |
| 125 | oms->pdata.caps |= MMC_CAP_NEEDS_POLL; | 142 | if (oms->detect_irq != NO_IRQ) { |
| 143 | oms->pdata.init = of_mmc_spi_init; | ||
| 144 | oms->pdata.exit = of_mmc_spi_exit; | ||
| 145 | } else { | ||
| 146 | oms->pdata.caps |= MMC_CAP_NEEDS_POLL; | ||
| 147 | } | ||
| 126 | 148 | ||
| 127 | dev->platform_data = &oms->pdata; | 149 | dev->platform_data = &oms->pdata; |
| 128 | return dev->platform_data; | 150 | return dev->platform_data; |
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index 26a86d235051..b038d2cfef26 100644 --- a/drivers/rtc/rtc-ds1390.c +++ b/drivers/rtc/rtc-ds1390.c | |||
| @@ -158,7 +158,7 @@ static int __devinit ds1390_probe(struct spi_device *spi) | |||
| 158 | 158 | ||
| 159 | static int __devexit ds1390_remove(struct spi_device *spi) | 159 | static int __devexit ds1390_remove(struct spi_device *spi) |
| 160 | { | 160 | { |
| 161 | struct ds1390 *chip = platform_get_drvdata(spi); | 161 | struct ds1390 *chip = spi_get_drvdata(spi); |
| 162 | 162 | ||
| 163 | rtc_device_unregister(chip->rtc); | 163 | rtc_device_unregister(chip->rtc); |
| 164 | kfree(chip); | 164 | kfree(chip); |
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c index a774ca35b5f7..bbd26228f532 100644 --- a/drivers/rtc/rtc-ds3234.c +++ b/drivers/rtc/rtc-ds3234.c | |||
| @@ -158,7 +158,7 @@ static int __devinit ds3234_probe(struct spi_device *spi) | |||
| 158 | 158 | ||
| 159 | static int __devexit ds3234_remove(struct spi_device *spi) | 159 | static int __devexit ds3234_remove(struct spi_device *spi) |
| 160 | { | 160 | { |
| 161 | struct rtc_device *rtc = platform_get_drvdata(spi); | 161 | struct rtc_device *rtc = spi_get_drvdata(spi); |
| 162 | 162 | ||
| 163 | rtc_device_unregister(rtc); | 163 | rtc_device_unregister(rtc); |
| 164 | return 0; | 164 | return 0; |
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c index c8c97a4169d4..e259ed76ae85 100644 --- a/drivers/rtc/rtc-m41t94.c +++ b/drivers/rtc/rtc-m41t94.c | |||
| @@ -136,7 +136,7 @@ static int __devinit m41t94_probe(struct spi_device *spi) | |||
| 136 | 136 | ||
| 137 | static int __devexit m41t94_remove(struct spi_device *spi) | 137 | static int __devexit m41t94_remove(struct spi_device *spi) |
| 138 | { | 138 | { |
| 139 | struct rtc_device *rtc = platform_get_drvdata(spi); | 139 | struct rtc_device *rtc = spi_get_drvdata(spi); |
| 140 | 140 | ||
| 141 | if (rtc) | 141 | if (rtc) |
| 142 | rtc_device_unregister(rtc); | 142 | rtc_device_unregister(rtc); |
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 7b90fc361b52..fc14b8dea0d7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
| @@ -53,6 +53,12 @@ if SPI_MASTER | |||
| 53 | 53 | ||
| 54 | comment "SPI Master Controller Drivers" | 54 | comment "SPI Master Controller Drivers" |
| 55 | 55 | ||
| 56 | config SPI_ALTERA | ||
| 57 | tristate "Altera SPI Controller" | ||
| 58 | select SPI_BITBANG | ||
| 59 | help | ||
| 60 | This is the driver for the Altera SPI Controller. | ||
| 61 | |||
| 56 | config SPI_ATH79 | 62 | config SPI_ATH79 |
| 57 | tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver" | 63 | tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver" |
| 58 | depends on ATH79 && GENERIC_GPIO | 64 | depends on ATH79 && GENERIC_GPIO |
| @@ -231,6 +237,13 @@ config SPI_FSL_ESPI | |||
| 231 | From MPC8536, 85xx platform uses the controller, and all P10xx, | 237 | From MPC8536, 85xx platform uses the controller, and all P10xx, |
| 232 | P20xx, P30xx,P40xx, P50xx uses this controller. | 238 | P20xx, P30xx,P40xx, P50xx uses this controller. |
| 233 | 239 | ||
| 240 | config SPI_OC_TINY | ||
| 241 | tristate "OpenCores tiny SPI" | ||
| 242 | depends on GENERIC_GPIO | ||
| 243 | select SPI_BITBANG | ||
| 244 | help | ||
| 245 | This is the driver for OpenCores tiny SPI master controller. | ||
| 246 | |||
| 234 | config SPI_OMAP_UWIRE | 247 | config SPI_OMAP_UWIRE |
| 235 | tristate "OMAP1 MicroWire" | 248 | tristate "OMAP1 MicroWire" |
| 236 | depends on ARCH_OMAP1 | 249 | depends on ARCH_OMAP1 |
| @@ -330,6 +343,12 @@ config SPI_SH_MSIOF | |||
| 330 | help | 343 | help |
| 331 | SPI driver for SuperH MSIOF blocks. | 344 | SPI driver for SuperH MSIOF blocks. |
| 332 | 345 | ||
| 346 | config SPI_SH | ||
| 347 | tristate "SuperH SPI controller" | ||
| 348 | depends on SUPERH | ||
| 349 | help | ||
| 350 | SPI driver for SuperH SPI blocks. | ||
| 351 | |||
| 333 | config SPI_SH_SCI | 352 | config SPI_SH_SCI |
| 334 | tristate "SuperH SCI SPI controller" | 353 | tristate "SuperH SCI SPI controller" |
| 335 | depends on SUPERH | 354 | depends on SUPERH |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index f3f31d988358..fd2fc5f6505f 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
| @@ -9,6 +9,7 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG | |||
| 9 | obj-$(CONFIG_SPI_MASTER) += spi.o | 9 | obj-$(CONFIG_SPI_MASTER) += spi.o |
| 10 | 10 | ||
| 11 | # SPI master controller drivers (bus) | 11 | # SPI master controller drivers (bus) |
| 12 | obj-$(CONFIG_SPI_ALTERA) += spi_altera.o | ||
| 12 | obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o | 13 | obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o |
| 13 | obj-$(CONFIG_SPI_ATH79) += ath79_spi.o | 14 | obj-$(CONFIG_SPI_ATH79) += ath79_spi.o |
| 14 | obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o | 15 | obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o |
| @@ -27,6 +28,7 @@ obj-$(CONFIG_SPI_IMX) += spi_imx.o | |||
| 27 | obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o | 28 | obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o |
| 28 | obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o | 29 | obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o |
| 29 | obj-$(CONFIG_SPI_PXA2XX_PCI) += pxa2xx_spi_pci.o | 30 | obj-$(CONFIG_SPI_PXA2XX_PCI) += pxa2xx_spi_pci.o |
| 31 | obj-$(CONFIG_SPI_OC_TINY) += spi_oc_tiny.o | ||
| 30 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o | 32 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o |
| 31 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o | 33 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o |
| 32 | obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o | 34 | obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o |
| @@ -47,6 +49,7 @@ obj-$(CONFIG_SPI_TI_SSP) += ti-ssp-spi.o | |||
| 47 | obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o | 49 | obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o |
| 48 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o | 50 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o |
| 49 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o | 51 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o |
| 52 | obj-$(CONFIG_SPI_SH) += spi_sh.o | ||
| 50 | obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o | 53 | obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o |
| 51 | obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o | 54 | obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o |
| 52 | obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o | 55 | obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o |
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 95e58c70a2c9..5c2b092a915e 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c | |||
| @@ -329,15 +329,16 @@ struct vendor_data { | |||
| 329 | /** | 329 | /** |
| 330 | * struct pl022 - This is the private SSP driver data structure | 330 | * struct pl022 - This is the private SSP driver data structure |
| 331 | * @adev: AMBA device model hookup | 331 | * @adev: AMBA device model hookup |
| 332 | * @vendor: Vendor data for the IP block | 332 | * @vendor: vendor data for the IP block |
| 333 | * @phybase: The physical memory where the SSP device resides | 333 | * @phybase: the physical memory where the SSP device resides |
| 334 | * @virtbase: The virtual memory where the SSP is mapped | 334 | * @virtbase: the virtual memory where the SSP is mapped |
| 335 | * @clk: outgoing clock "SPICLK" for the SPI bus | ||
| 335 | * @master: SPI framework hookup | 336 | * @master: SPI framework hookup |
| 336 | * @master_info: controller-specific data from machine setup | 337 | * @master_info: controller-specific data from machine setup |
| 337 | * @regs: SSP controller register's virtual address | ||
| 338 | * @pump_messages: Work struct for scheduling work to the workqueue | ||
| 339 | * @lock: spinlock to syncronise access to driver data | ||
| 340 | * @workqueue: a workqueue on which any spi_message request is queued | 338 | * @workqueue: a workqueue on which any spi_message request is queued |
| 339 | * @pump_messages: work struct for scheduling work to the workqueue | ||
| 340 | * @queue_lock: spinlock to syncronise access to message queue | ||
| 341 | * @queue: message queue | ||
| 341 | * @busy: workqueue is busy | 342 | * @busy: workqueue is busy |
| 342 | * @running: workqueue is running | 343 | * @running: workqueue is running |
| 343 | * @pump_transfers: Tasklet used in Interrupt Transfer mode | 344 | * @pump_transfers: Tasklet used in Interrupt Transfer mode |
| @@ -348,8 +349,14 @@ struct vendor_data { | |||
| 348 | * @tx_end: end position in TX buffer to be read | 349 | * @tx_end: end position in TX buffer to be read |
| 349 | * @rx: current position in RX buffer to be written | 350 | * @rx: current position in RX buffer to be written |
| 350 | * @rx_end: end position in RX buffer to be written | 351 | * @rx_end: end position in RX buffer to be written |
| 351 | * @readingtype: the type of read currently going on | 352 | * @read: the type of read currently going on |
| 352 | * @writingtype: the type or write currently going on | 353 | * @write: the type of write currently going on |
| 354 | * @exp_fifo_level: expected FIFO level | ||
| 355 | * @dma_rx_channel: optional channel for RX DMA | ||
| 356 | * @dma_tx_channel: optional channel for TX DMA | ||
| 357 | * @sgt_rx: scattertable for the RX transfer | ||
| 358 | * @sgt_tx: scattertable for the TX transfer | ||
| 359 | * @dummypage: a dummy page used for driving data on the bus with DMA | ||
| 353 | */ | 360 | */ |
| 354 | struct pl022 { | 361 | struct pl022 { |
| 355 | struct amba_device *adev; | 362 | struct amba_device *adev; |
| @@ -397,8 +404,8 @@ struct pl022 { | |||
| 397 | * @cpsr: Value of Clock prescale register | 404 | * @cpsr: Value of Clock prescale register |
| 398 | * @n_bytes: how many bytes(power of 2) reqd for a given data width of client | 405 | * @n_bytes: how many bytes(power of 2) reqd for a given data width of client |
| 399 | * @enable_dma: Whether to enable DMA or not | 406 | * @enable_dma: Whether to enable DMA or not |
| 400 | * @write: function ptr to be used to write when doing xfer for this chip | ||
| 401 | * @read: function ptr to be used to read when doing xfer for this chip | 407 | * @read: function ptr to be used to read when doing xfer for this chip |
| 408 | * @write: function ptr to be used to write when doing xfer for this chip | ||
| 402 | * @cs_control: chip select callback provided by chip | 409 | * @cs_control: chip select callback provided by chip |
| 403 | * @xfer_type: polling/interrupt/DMA | 410 | * @xfer_type: polling/interrupt/DMA |
| 404 | * | 411 | * |
| @@ -508,9 +515,10 @@ static void giveback(struct pl022 *pl022) | |||
| 508 | msg->state = NULL; | 515 | msg->state = NULL; |
| 509 | if (msg->complete) | 516 | if (msg->complete) |
| 510 | msg->complete(msg->context); | 517 | msg->complete(msg->context); |
| 511 | /* This message is completed, so let's turn off the clocks! */ | 518 | /* This message is completed, so let's turn off the clocks & power */ |
| 512 | clk_disable(pl022->clk); | 519 | clk_disable(pl022->clk); |
| 513 | amba_pclk_disable(pl022->adev); | 520 | amba_pclk_disable(pl022->adev); |
| 521 | amba_vcore_disable(pl022->adev); | ||
| 514 | } | 522 | } |
| 515 | 523 | ||
| 516 | /** | 524 | /** |
| @@ -917,7 +925,6 @@ static int configure_dma(struct pl022 *pl022) | |||
| 917 | struct dma_chan *txchan = pl022->dma_tx_channel; | 925 | struct dma_chan *txchan = pl022->dma_tx_channel; |
| 918 | struct dma_async_tx_descriptor *rxdesc; | 926 | struct dma_async_tx_descriptor *rxdesc; |
| 919 | struct dma_async_tx_descriptor *txdesc; | 927 | struct dma_async_tx_descriptor *txdesc; |
| 920 | dma_cookie_t cookie; | ||
| 921 | 928 | ||
| 922 | /* Check that the channels are available */ | 929 | /* Check that the channels are available */ |
| 923 | if (!rxchan || !txchan) | 930 | if (!rxchan || !txchan) |
| @@ -962,10 +969,8 @@ static int configure_dma(struct pl022 *pl022) | |||
| 962 | tx_conf.dst_addr_width = rx_conf.src_addr_width; | 969 | tx_conf.dst_addr_width = rx_conf.src_addr_width; |
| 963 | BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width); | 970 | BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width); |
| 964 | 971 | ||
| 965 | rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG, | 972 | dmaengine_slave_config(rxchan, &rx_conf); |
| 966 | (unsigned long) &rx_conf); | 973 | dmaengine_slave_config(txchan, &tx_conf); |
| 967 | txchan->device->device_control(txchan, DMA_SLAVE_CONFIG, | ||
| 968 | (unsigned long) &tx_conf); | ||
| 969 | 974 | ||
| 970 | /* Create sglists for the transfers */ | 975 | /* Create sglists for the transfers */ |
| 971 | pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1; | 976 | pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1; |
| @@ -1018,23 +1023,17 @@ static int configure_dma(struct pl022 *pl022) | |||
| 1018 | rxdesc->callback_param = pl022; | 1023 | rxdesc->callback_param = pl022; |
| 1019 | 1024 | ||
| 1020 | /* Submit and fire RX and TX with TX last so we're ready to read! */ | 1025 | /* Submit and fire RX and TX with TX last so we're ready to read! */ |
| 1021 | cookie = rxdesc->tx_submit(rxdesc); | 1026 | dmaengine_submit(rxdesc); |
| 1022 | if (dma_submit_error(cookie)) | 1027 | dmaengine_submit(txdesc); |
| 1023 | goto err_submit_rx; | 1028 | dma_async_issue_pending(rxchan); |
| 1024 | cookie = txdesc->tx_submit(txdesc); | 1029 | dma_async_issue_pending(txchan); |
| 1025 | if (dma_submit_error(cookie)) | ||
| 1026 | goto err_submit_tx; | ||
| 1027 | rxchan->device->device_issue_pending(rxchan); | ||
| 1028 | txchan->device->device_issue_pending(txchan); | ||
| 1029 | 1030 | ||
| 1030 | return 0; | 1031 | return 0; |
| 1031 | 1032 | ||
| 1032 | err_submit_tx: | ||
| 1033 | err_submit_rx: | ||
| 1034 | err_txdesc: | 1033 | err_txdesc: |
| 1035 | txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0); | 1034 | dmaengine_terminate_all(txchan); |
| 1036 | err_rxdesc: | 1035 | err_rxdesc: |
| 1037 | rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0); | 1036 | dmaengine_terminate_all(rxchan); |
| 1038 | dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl, | 1037 | dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl, |
| 1039 | pl022->sgt_tx.nents, DMA_TO_DEVICE); | 1038 | pl022->sgt_tx.nents, DMA_TO_DEVICE); |
| 1040 | err_tx_sgmap: | 1039 | err_tx_sgmap: |
| @@ -1101,8 +1100,8 @@ static void terminate_dma(struct pl022 *pl022) | |||
| 1101 | struct dma_chan *rxchan = pl022->dma_rx_channel; | 1100 | struct dma_chan *rxchan = pl022->dma_rx_channel; |
| 1102 | struct dma_chan *txchan = pl022->dma_tx_channel; | 1101 | struct dma_chan *txchan = pl022->dma_tx_channel; |
| 1103 | 1102 | ||
| 1104 | rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0); | 1103 | dmaengine_terminate_all(rxchan); |
| 1105 | txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0); | 1104 | dmaengine_terminate_all(txchan); |
| 1106 | unmap_free_dma_scatter(pl022); | 1105 | unmap_free_dma_scatter(pl022); |
| 1107 | } | 1106 | } |
| 1108 | 1107 | ||
| @@ -1482,9 +1481,11 @@ static void pump_messages(struct work_struct *work) | |||
| 1482 | /* Setup the SPI using the per chip configuration */ | 1481 | /* Setup the SPI using the per chip configuration */ |
| 1483 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); | 1482 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); |
| 1484 | /* | 1483 | /* |
| 1485 | * We enable the clocks here, then the clocks will be disabled when | 1484 | * We enable the core voltage and clocks here, then the clocks |
| 1486 | * giveback() is called in each method (poll/interrupt/DMA) | 1485 | * and core will be disabled when giveback() is called in each method |
| 1486 | * (poll/interrupt/DMA) | ||
| 1487 | */ | 1487 | */ |
| 1488 | amba_vcore_enable(pl022->adev); | ||
| 1488 | amba_pclk_enable(pl022->adev); | 1489 | amba_pclk_enable(pl022->adev); |
| 1489 | clk_enable(pl022->clk); | 1490 | clk_enable(pl022->clk); |
| 1490 | restore_state(pl022); | 1491 | restore_state(pl022); |
| @@ -1910,8 +1911,6 @@ static int pl022_setup(struct spi_device *spi) | |||
| 1910 | && ((pl022->master_info)->enable_dma)) { | 1911 | && ((pl022->master_info)->enable_dma)) { |
| 1911 | chip->enable_dma = true; | 1912 | chip->enable_dma = true; |
| 1912 | dev_dbg(&spi->dev, "DMA mode set in controller state\n"); | 1913 | dev_dbg(&spi->dev, "DMA mode set in controller state\n"); |
| 1913 | if (status < 0) | ||
| 1914 | goto err_config_params; | ||
| 1915 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, | 1914 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, |
| 1916 | SSP_DMACR_MASK_RXDMAE, 0); | 1915 | SSP_DMACR_MASK_RXDMAE, 0); |
| 1917 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, | 1916 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, |
| @@ -2130,8 +2129,12 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
| 2130 | goto err_spi_register; | 2129 | goto err_spi_register; |
| 2131 | } | 2130 | } |
| 2132 | dev_dbg(dev, "probe succeded\n"); | 2131 | dev_dbg(dev, "probe succeded\n"); |
| 2133 | /* Disable the silicon block pclk and clock it when needed */ | 2132 | /* |
| 2133 | * Disable the silicon block pclk and any voltage domain and just | ||
| 2134 | * power it up and clock it when it's needed | ||
| 2135 | */ | ||
| 2134 | amba_pclk_disable(adev); | 2136 | amba_pclk_disable(adev); |
| 2137 | amba_vcore_disable(adev); | ||
| 2135 | return 0; | 2138 | return 0; |
| 2136 | 2139 | ||
| 2137 | err_spi_register: | 2140 | err_spi_register: |
| @@ -2196,9 +2199,11 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state) | |||
| 2196 | return status; | 2199 | return status; |
| 2197 | } | 2200 | } |
| 2198 | 2201 | ||
| 2202 | amba_vcore_enable(adev); | ||
| 2199 | amba_pclk_enable(adev); | 2203 | amba_pclk_enable(adev); |
| 2200 | load_ssp_default_config(pl022); | 2204 | load_ssp_default_config(pl022); |
| 2201 | amba_pclk_disable(adev); | 2205 | amba_pclk_disable(adev); |
| 2206 | amba_vcore_disable(adev); | ||
| 2202 | dev_dbg(&adev->dev, "suspended\n"); | 2207 | dev_dbg(&adev->dev, "suspended\n"); |
| 2203 | return 0; | 2208 | return 0; |
| 2204 | } | 2209 | } |
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 166a879fd9e8..1f0ed8005c91 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c | |||
| @@ -571,6 +571,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
| 571 | unsigned long tx_reg, rx_reg; | 571 | unsigned long tx_reg, rx_reg; |
| 572 | struct edmacc_param param; | 572 | struct edmacc_param param; |
| 573 | void *rx_buf; | 573 | void *rx_buf; |
| 574 | int b, c; | ||
| 574 | 575 | ||
| 575 | dma = &dspi->dma; | 576 | dma = &dspi->dma; |
| 576 | 577 | ||
| @@ -591,22 +592,38 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
| 591 | 592 | ||
| 592 | if (t->tx_buf) { | 593 | if (t->tx_buf) { |
| 593 | t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf, | 594 | t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf, |
| 594 | dspi->wcount, DMA_TO_DEVICE); | 595 | t->len, DMA_TO_DEVICE); |
| 595 | if (dma_mapping_error(&spi->dev, t->tx_dma)) { | 596 | if (dma_mapping_error(&spi->dev, t->tx_dma)) { |
| 596 | dev_dbg(sdev, "Unable to DMA map %d bytes" | 597 | dev_dbg(sdev, "Unable to DMA map %d bytes" |
| 597 | "TX buffer\n", dspi->wcount); | 598 | "TX buffer\n", t->len); |
| 598 | return -ENOMEM; | 599 | return -ENOMEM; |
| 599 | } | 600 | } |
| 600 | } | 601 | } |
| 601 | 602 | ||
| 603 | /* | ||
| 604 | * If number of words is greater than 65535, then we need | ||
| 605 | * to configure a 3 dimension transfer. Use the BCNTRLD | ||
| 606 | * feature to allow for transfers that aren't even multiples | ||
| 607 | * of 65535 (or any other possible b size) by first transferring | ||
| 608 | * the remainder amount then grabbing the next N blocks of | ||
| 609 | * 65535 words. | ||
| 610 | */ | ||
| 611 | |||
| 612 | c = dspi->wcount / (SZ_64K - 1); /* N 65535 Blocks */ | ||
| 613 | b = dspi->wcount - c * (SZ_64K - 1); /* Remainder */ | ||
| 614 | if (b) | ||
| 615 | c++; | ||
| 616 | else | ||
| 617 | b = SZ_64K - 1; | ||
| 618 | |||
| 602 | param.opt = TCINTEN | EDMA_TCC(dma->tx_channel); | 619 | param.opt = TCINTEN | EDMA_TCC(dma->tx_channel); |
| 603 | param.src = t->tx_buf ? t->tx_dma : tx_reg; | 620 | param.src = t->tx_buf ? t->tx_dma : tx_reg; |
| 604 | param.a_b_cnt = dspi->wcount << 16 | data_type; | 621 | param.a_b_cnt = b << 16 | data_type; |
| 605 | param.dst = tx_reg; | 622 | param.dst = tx_reg; |
| 606 | param.src_dst_bidx = t->tx_buf ? data_type : 0; | 623 | param.src_dst_bidx = t->tx_buf ? data_type : 0; |
| 607 | param.link_bcntrld = 0xffff; | 624 | param.link_bcntrld = 0xffffffff; |
| 608 | param.src_dst_cidx = 0; | 625 | param.src_dst_cidx = t->tx_buf ? data_type : 0; |
| 609 | param.ccnt = 1; | 626 | param.ccnt = c; |
| 610 | edma_write_slot(dma->tx_channel, ¶m); | 627 | edma_write_slot(dma->tx_channel, ¶m); |
| 611 | edma_link(dma->tx_channel, dma->dummy_param_slot); | 628 | edma_link(dma->tx_channel, dma->dummy_param_slot); |
| 612 | 629 | ||
| @@ -624,7 +641,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
| 624 | 641 | ||
| 625 | if (t->rx_buf) { | 642 | if (t->rx_buf) { |
| 626 | rx_buf = t->rx_buf; | 643 | rx_buf = t->rx_buf; |
| 627 | rx_buf_count = dspi->rcount; | 644 | rx_buf_count = t->len; |
| 628 | } else { | 645 | } else { |
| 629 | rx_buf = dspi->rx_tmp_buf; | 646 | rx_buf = dspi->rx_tmp_buf; |
| 630 | rx_buf_count = sizeof(dspi->rx_tmp_buf); | 647 | rx_buf_count = sizeof(dspi->rx_tmp_buf); |
| @@ -636,19 +653,19 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
| 636 | dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n", | 653 | dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n", |
| 637 | rx_buf_count); | 654 | rx_buf_count); |
| 638 | if (t->tx_buf) | 655 | if (t->tx_buf) |
| 639 | dma_unmap_single(NULL, t->tx_dma, dspi->wcount, | 656 | dma_unmap_single(NULL, t->tx_dma, t->len, |
| 640 | DMA_TO_DEVICE); | 657 | DMA_TO_DEVICE); |
| 641 | return -ENOMEM; | 658 | return -ENOMEM; |
| 642 | } | 659 | } |
| 643 | 660 | ||
| 644 | param.opt = TCINTEN | EDMA_TCC(dma->rx_channel); | 661 | param.opt = TCINTEN | EDMA_TCC(dma->rx_channel); |
| 645 | param.src = rx_reg; | 662 | param.src = rx_reg; |
| 646 | param.a_b_cnt = dspi->rcount << 16 | data_type; | 663 | param.a_b_cnt = b << 16 | data_type; |
| 647 | param.dst = t->rx_dma; | 664 | param.dst = t->rx_dma; |
| 648 | param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16; | 665 | param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16; |
| 649 | param.link_bcntrld = 0xffff; | 666 | param.link_bcntrld = 0xffffffff; |
| 650 | param.src_dst_cidx = 0; | 667 | param.src_dst_cidx = (t->rx_buf ? data_type : 0) << 16; |
| 651 | param.ccnt = 1; | 668 | param.ccnt = c; |
| 652 | edma_write_slot(dma->rx_channel, ¶m); | 669 | edma_write_slot(dma->rx_channel, ¶m); |
| 653 | 670 | ||
| 654 | if (pdata->cshold_bug) | 671 | if (pdata->cshold_bug) |
| @@ -675,7 +692,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
| 675 | if (spicfg->io_type == SPI_IO_TYPE_DMA) { | 692 | if (spicfg->io_type == SPI_IO_TYPE_DMA) { |
| 676 | 693 | ||
| 677 | if (t->tx_buf) | 694 | if (t->tx_buf) |
| 678 | dma_unmap_single(NULL, t->tx_dma, dspi->wcount, | 695 | dma_unmap_single(NULL, t->tx_dma, t->len, |
| 679 | DMA_TO_DEVICE); | 696 | DMA_TO_DEVICE); |
| 680 | 697 | ||
| 681 | dma_unmap_single(NULL, t->rx_dma, rx_buf_count, | 698 | dma_unmap_single(NULL, t->rx_dma, rx_buf_count, |
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index 22af77f98816..9a6196461b27 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c | |||
| @@ -22,10 +22,10 @@ | |||
| 22 | #include <linux/highmem.h> | 22 | #include <linux/highmem.h> |
| 23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | |||
| 26 | #include <linux/spi/dw_spi.h> | ||
| 27 | #include <linux/spi/spi.h> | 25 | #include <linux/spi/spi.h> |
| 28 | 26 | ||
| 27 | #include "dw_spi.h" | ||
| 28 | |||
| 29 | #ifdef CONFIG_DEBUG_FS | 29 | #ifdef CONFIG_DEBUG_FS |
| 30 | #include <linux/debugfs.h> | 30 | #include <linux/debugfs.h> |
| 31 | #endif | 31 | #endif |
diff --git a/include/linux/spi/dw_spi.h b/drivers/spi/dw_spi.h index 6cd10f6ad472..fb0bce564844 100644 --- a/include/linux/spi/dw_spi.h +++ b/drivers/spi/dw_spi.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define DW_SPI_HEADER_H | 2 | #define DW_SPI_HEADER_H |
| 3 | 3 | ||
| 4 | #include <linux/io.h> | 4 | #include <linux/io.h> |
| 5 | #include <linux/scatterlist.h> | ||
| 5 | 6 | ||
| 6 | /* Bit fields in CTRLR0 */ | 7 | /* Bit fields in CTRLR0 */ |
| 7 | #define SPI_DFS_OFFSET 0 | 8 | #define SPI_DFS_OFFSET 0 |
diff --git a/drivers/spi/dw_spi_mid.c b/drivers/spi/dw_spi_mid.c index c91c966e0717..489178243d88 100644 --- a/drivers/spi/dw_spi_mid.c +++ b/drivers/spi/dw_spi_mid.c | |||
| @@ -22,7 +22,8 @@ | |||
| 22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
| 25 | #include <linux/spi/dw_spi.h> | 25 | |
| 26 | #include "dw_spi.h" | ||
| 26 | 27 | ||
| 27 | #ifdef CONFIG_SPI_DW_MID_DMA | 28 | #ifdef CONFIG_SPI_DW_MID_DMA |
| 28 | #include <linux/intel_mid_dma.h> | 29 | #include <linux/intel_mid_dma.h> |
diff --git a/drivers/spi/dw_spi_mmio.c b/drivers/spi/dw_spi_mmio.c index 2fa012c109bc..e0e813dad150 100644 --- a/drivers/spi/dw_spi_mmio.c +++ b/drivers/spi/dw_spi_mmio.c | |||
| @@ -13,8 +13,10 @@ | |||
| 13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/spi/dw_spi.h> | ||
| 17 | #include <linux/spi/spi.h> | 16 | #include <linux/spi/spi.h> |
| 17 | #include <linux/scatterlist.h> | ||
| 18 | |||
| 19 | #include "dw_spi.h" | ||
| 18 | 20 | ||
| 19 | #define DRIVER_NAME "dw_spi_mmio" | 21 | #define DRIVER_NAME "dw_spi_mmio" |
| 20 | 22 | ||
diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/dw_spi_pci.c index 49ec3aa1219f..ad260aa5e526 100644 --- a/drivers/spi/dw_spi_pci.c +++ b/drivers/spi/dw_spi_pci.c | |||
| @@ -20,9 +20,10 @@ | |||
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/spi/dw_spi.h> | ||
| 24 | #include <linux/spi/spi.h> | 23 | #include <linux/spi/spi.h> |
| 25 | 24 | ||
| 25 | #include "dw_spi.h" | ||
| 26 | |||
| 26 | #define DRIVER_NAME "dw_spi_pci" | 27 | #define DRIVER_NAME "dw_spi_pci" |
| 27 | 28 | ||
| 28 | struct dw_spi_pci { | 29 | struct dw_spi_pci { |
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index 36501adc125d..3a5ed06d3d2f 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c | |||
| @@ -467,6 +467,9 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
| 467 | rx_reg = base + OMAP2_MCSPI_RX0; | 467 | rx_reg = base + OMAP2_MCSPI_RX0; |
| 468 | chstat_reg = base + OMAP2_MCSPI_CHSTAT0; | 468 | chstat_reg = base + OMAP2_MCSPI_CHSTAT0; |
| 469 | 469 | ||
| 470 | if (c < (word_len>>3)) | ||
| 471 | return 0; | ||
| 472 | |||
| 470 | if (word_len <= 8) { | 473 | if (word_len <= 8) { |
| 471 | u8 *rx; | 474 | u8 *rx; |
| 472 | const u8 *tx; | 475 | const u8 *tx; |
| @@ -514,7 +517,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
| 514 | dev_vdbg(&spi->dev, "read-%d %02x\n", | 517 | dev_vdbg(&spi->dev, "read-%d %02x\n", |
| 515 | word_len, *(rx - 1)); | 518 | word_len, *(rx - 1)); |
| 516 | } | 519 | } |
| 517 | } while (c); | 520 | } while (c > (word_len>>3)); |
| 518 | } else if (word_len <= 16) { | 521 | } else if (word_len <= 16) { |
| 519 | u16 *rx; | 522 | u16 *rx; |
| 520 | const u16 *tx; | 523 | const u16 *tx; |
| @@ -561,7 +564,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
| 561 | dev_vdbg(&spi->dev, "read-%d %04x\n", | 564 | dev_vdbg(&spi->dev, "read-%d %04x\n", |
| 562 | word_len, *(rx - 1)); | 565 | word_len, *(rx - 1)); |
| 563 | } | 566 | } |
| 564 | } while (c); | 567 | } while (c > (word_len>>3)); |
| 565 | } else if (word_len <= 32) { | 568 | } else if (word_len <= 32) { |
| 566 | u32 *rx; | 569 | u32 *rx; |
| 567 | const u32 *tx; | 570 | const u32 *tx; |
| @@ -608,7 +611,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
| 608 | dev_vdbg(&spi->dev, "read-%d %08x\n", | 611 | dev_vdbg(&spi->dev, "read-%d %08x\n", |
| 609 | word_len, *(rx - 1)); | 612 | word_len, *(rx - 1)); |
| 610 | } | 613 | } |
| 611 | } while (c); | 614 | } while (c > (word_len>>3)); |
| 612 | } | 615 | } |
| 613 | 616 | ||
| 614 | /* for TX_ONLY mode, be sure all words have shifted out */ | 617 | /* for TX_ONLY mode, be sure all words have shifted out */ |
| @@ -631,6 +634,17 @@ out: | |||
| 631 | return count - c; | 634 | return count - c; |
| 632 | } | 635 | } |
| 633 | 636 | ||
| 637 | static u32 omap2_mcspi_calc_divisor(u32 speed_hz) | ||
| 638 | { | ||
| 639 | u32 div; | ||
| 640 | |||
| 641 | for (div = 0; div < 15; div++) | ||
| 642 | if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div)) | ||
| 643 | return div; | ||
| 644 | |||
| 645 | return 15; | ||
| 646 | } | ||
| 647 | |||
| 634 | /* called only when no transfer is active to this device */ | 648 | /* called only when no transfer is active to this device */ |
| 635 | static int omap2_mcspi_setup_transfer(struct spi_device *spi, | 649 | static int omap2_mcspi_setup_transfer(struct spi_device *spi, |
| 636 | struct spi_transfer *t) | 650 | struct spi_transfer *t) |
| @@ -653,12 +667,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
| 653 | if (t && t->speed_hz) | 667 | if (t && t->speed_hz) |
| 654 | speed_hz = t->speed_hz; | 668 | speed_hz = t->speed_hz; |
| 655 | 669 | ||
| 656 | if (speed_hz) { | 670 | speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); |
| 657 | while (div <= 15 && (OMAP2_MCSPI_MAX_FREQ / (1 << div)) | 671 | div = omap2_mcspi_calc_divisor(speed_hz); |
| 658 | > speed_hz) | ||
| 659 | div++; | ||
| 660 | } else | ||
| 661 | div = 15; | ||
| 662 | 672 | ||
| 663 | l = mcspi_cached_chconf0(spi); | 673 | l = mcspi_cached_chconf0(spi); |
| 664 | 674 | ||
| @@ -695,7 +705,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
| 695 | mcspi_write_chconf0(spi, l); | 705 | mcspi_write_chconf0(spi, l); |
| 696 | 706 | ||
| 697 | dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", | 707 | dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", |
| 698 | OMAP2_MCSPI_MAX_FREQ / (1 << div), | 708 | OMAP2_MCSPI_MAX_FREQ >> div, |
| 699 | (spi->mode & SPI_CPHA) ? "trailing" : "leading", | 709 | (spi->mode & SPI_CPHA) ? "trailing" : "leading", |
| 700 | (spi->mode & SPI_CPOL) ? "inverted" : "normal"); | 710 | (spi->mode & SPI_CPOL) ? "inverted" : "normal"); |
| 701 | 711 | ||
| @@ -996,10 +1006,10 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | |||
| 996 | t->bits_per_word); | 1006 | t->bits_per_word); |
| 997 | return -EINVAL; | 1007 | return -EINVAL; |
| 998 | } | 1008 | } |
| 999 | if (t->speed_hz && t->speed_hz < OMAP2_MCSPI_MAX_FREQ/(1<<16)) { | 1009 | if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) { |
| 1000 | dev_dbg(&spi->dev, "%d Hz max exceeds %d\n", | 1010 | dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n", |
| 1001 | t->speed_hz, | 1011 | t->speed_hz, |
| 1002 | OMAP2_MCSPI_MAX_FREQ/(1<<16)); | 1012 | OMAP2_MCSPI_MAX_FREQ >> 15); |
| 1003 | return -EINVAL; | 1013 | return -EINVAL; |
| 1004 | } | 1014 | } |
| 1005 | 1015 | ||
diff --git a/drivers/spi/spi_altera.c b/drivers/spi/spi_altera.c new file mode 100644 index 000000000000..4813a63ce6fb --- /dev/null +++ b/drivers/spi/spi_altera.c | |||
| @@ -0,0 +1,339 @@ | |||
| 1 | /* | ||
| 2 | * Altera SPI driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw> | ||
| 5 | * | ||
| 6 | * Based on spi_s3c24xx.c, which is: | ||
| 7 | * Copyright (c) 2006 Ben Dooks | ||
| 8 | * Copyright (c) 2006 Simtec Electronics | ||
| 9 | * Ben Dooks <ben@simtec.co.uk> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/interrupt.h> | ||
| 18 | #include <linux/errno.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/spi/spi.h> | ||
| 21 | #include <linux/spi/spi_bitbang.h> | ||
| 22 | #include <linux/io.h> | ||
| 23 | #include <linux/of.h> | ||
| 24 | |||
| 25 | #define DRV_NAME "spi_altera" | ||
| 26 | |||
| 27 | #define ALTERA_SPI_RXDATA 0 | ||
| 28 | #define ALTERA_SPI_TXDATA 4 | ||
| 29 | #define ALTERA_SPI_STATUS 8 | ||
| 30 | #define ALTERA_SPI_CONTROL 12 | ||
| 31 | #define ALTERA_SPI_SLAVE_SEL 20 | ||
| 32 | |||
| 33 | #define ALTERA_SPI_STATUS_ROE_MSK 0x8 | ||
| 34 | #define ALTERA_SPI_STATUS_TOE_MSK 0x10 | ||
| 35 | #define ALTERA_SPI_STATUS_TMT_MSK 0x20 | ||
| 36 | #define ALTERA_SPI_STATUS_TRDY_MSK 0x40 | ||
| 37 | #define ALTERA_SPI_STATUS_RRDY_MSK 0x80 | ||
| 38 | #define ALTERA_SPI_STATUS_E_MSK 0x100 | ||
| 39 | |||
| 40 | #define ALTERA_SPI_CONTROL_IROE_MSK 0x8 | ||
| 41 | #define ALTERA_SPI_CONTROL_ITOE_MSK 0x10 | ||
| 42 | #define ALTERA_SPI_CONTROL_ITRDY_MSK 0x40 | ||
| 43 | #define ALTERA_SPI_CONTROL_IRRDY_MSK 0x80 | ||
| 44 | #define ALTERA_SPI_CONTROL_IE_MSK 0x100 | ||
| 45 | #define ALTERA_SPI_CONTROL_SSO_MSK 0x400 | ||
| 46 | |||
| 47 | struct altera_spi { | ||
| 48 | /* bitbang has to be first */ | ||
| 49 | struct spi_bitbang bitbang; | ||
| 50 | struct completion done; | ||
| 51 | |||
| 52 | void __iomem *base; | ||
| 53 | int irq; | ||
| 54 | int len; | ||
| 55 | int count; | ||
| 56 | int bytes_per_word; | ||
| 57 | unsigned long imr; | ||
| 58 | |||
| 59 | /* data buffers */ | ||
| 60 | const unsigned char *tx; | ||
| 61 | unsigned char *rx; | ||
| 62 | }; | ||
| 63 | |||
| 64 | static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev) | ||
| 65 | { | ||
| 66 | return spi_master_get_devdata(sdev->master); | ||
| 67 | } | ||
| 68 | |||
| 69 | static void altera_spi_chipsel(struct spi_device *spi, int value) | ||
| 70 | { | ||
| 71 | struct altera_spi *hw = altera_spi_to_hw(spi); | ||
| 72 | |||
| 73 | if (spi->mode & SPI_CS_HIGH) { | ||
| 74 | switch (value) { | ||
| 75 | case BITBANG_CS_INACTIVE: | ||
| 76 | writel(1 << spi->chip_select, | ||
| 77 | hw->base + ALTERA_SPI_SLAVE_SEL); | ||
| 78 | hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK; | ||
| 79 | writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); | ||
| 80 | break; | ||
| 81 | |||
| 82 | case BITBANG_CS_ACTIVE: | ||
| 83 | hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK; | ||
| 84 | writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); | ||
| 85 | writel(0, hw->base + ALTERA_SPI_SLAVE_SEL); | ||
| 86 | break; | ||
| 87 | } | ||
| 88 | } else { | ||
| 89 | switch (value) { | ||
| 90 | case BITBANG_CS_INACTIVE: | ||
| 91 | hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK; | ||
| 92 | writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); | ||
| 93 | break; | ||
| 94 | |||
| 95 | case BITBANG_CS_ACTIVE: | ||
| 96 | writel(1 << spi->chip_select, | ||
| 97 | hw->base + ALTERA_SPI_SLAVE_SEL); | ||
| 98 | hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK; | ||
| 99 | writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); | ||
| 100 | break; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | static int altera_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) | ||
| 106 | { | ||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static int altera_spi_setup(struct spi_device *spi) | ||
| 111 | { | ||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | static inline unsigned int hw_txbyte(struct altera_spi *hw, int count) | ||
| 116 | { | ||
| 117 | if (hw->tx) { | ||
| 118 | switch (hw->bytes_per_word) { | ||
| 119 | case 1: | ||
| 120 | return hw->tx[count]; | ||
| 121 | case 2: | ||
| 122 | return (hw->tx[count * 2] | ||
| 123 | | (hw->tx[count * 2 + 1] << 8)); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t) | ||
| 130 | { | ||
| 131 | struct altera_spi *hw = altera_spi_to_hw(spi); | ||
| 132 | |||
| 133 | hw->tx = t->tx_buf; | ||
| 134 | hw->rx = t->rx_buf; | ||
| 135 | hw->count = 0; | ||
| 136 | hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8; | ||
| 137 | hw->len = t->len / hw->bytes_per_word; | ||
| 138 | |||
| 139 | if (hw->irq >= 0) { | ||
| 140 | /* enable receive interrupt */ | ||
| 141 | hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK; | ||
| 142 | writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); | ||
| 143 | |||
| 144 | /* send the first byte */ | ||
| 145 | writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA); | ||
| 146 | |||
| 147 | wait_for_completion(&hw->done); | ||
| 148 | /* disable receive interrupt */ | ||
| 149 | hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK; | ||
| 150 | writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); | ||
| 151 | } else { | ||
| 152 | /* send the first byte */ | ||
| 153 | writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA); | ||
| 154 | |||
| 155 | while (1) { | ||
| 156 | unsigned int rxd; | ||
| 157 | |||
| 158 | while (!(readl(hw->base + ALTERA_SPI_STATUS) & | ||
| 159 | ALTERA_SPI_STATUS_RRDY_MSK)) | ||
| 160 | cpu_relax(); | ||
| 161 | |||
| 162 | rxd = readl(hw->base + ALTERA_SPI_RXDATA); | ||
| 163 | if (hw->rx) { | ||
| 164 | switch (hw->bytes_per_word) { | ||
| 165 | case 1: | ||
| 166 | hw->rx[hw->count] = rxd; | ||
| 167 | break; | ||
| 168 | case 2: | ||
| 169 | hw->rx[hw->count * 2] = rxd; | ||
| 170 | hw->rx[hw->count * 2 + 1] = rxd >> 8; | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | hw->count++; | ||
| 176 | |||
| 177 | if (hw->count < hw->len) | ||
| 178 | writel(hw_txbyte(hw, hw->count), | ||
| 179 | hw->base + ALTERA_SPI_TXDATA); | ||
| 180 | else | ||
| 181 | break; | ||
| 182 | } | ||
| 183 | |||
| 184 | } | ||
| 185 | |||
| 186 | return hw->count * hw->bytes_per_word; | ||
| 187 | } | ||
| 188 | |||
| 189 | static irqreturn_t altera_spi_irq(int irq, void *dev) | ||
| 190 | { | ||
| 191 | struct altera_spi *hw = dev; | ||
| 192 | unsigned int rxd; | ||
| 193 | |||
| 194 | rxd = readl(hw->base + ALTERA_SPI_RXDATA); | ||
| 195 | if (hw->rx) { | ||
| 196 | switch (hw->bytes_per_word) { | ||
| 197 | case 1: | ||
| 198 | hw->rx[hw->count] = rxd; | ||
| 199 | break; | ||
| 200 | case 2: | ||
| 201 | hw->rx[hw->count * 2] = rxd; | ||
| 202 | hw->rx[hw->count * 2 + 1] = rxd >> 8; | ||
| 203 | break; | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | hw->count++; | ||
| 208 | |||
| 209 | if (hw->count < hw->len) | ||
| 210 | writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA); | ||
| 211 | else | ||
| 212 | complete(&hw->done); | ||
| 213 | |||
| 214 | return IRQ_HANDLED; | ||
| 215 | } | ||
| 216 | |||
| 217 | static int __devinit altera_spi_probe(struct platform_device *pdev) | ||
| 218 | { | ||
| 219 | struct altera_spi_platform_data *platp = pdev->dev.platform_data; | ||
| 220 | struct altera_spi *hw; | ||
| 221 | struct spi_master *master; | ||
| 222 | struct resource *res; | ||
| 223 | int err = -ENODEV; | ||
| 224 | |||
| 225 | master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi)); | ||
| 226 | if (!master) | ||
| 227 | return err; | ||
| 228 | |||
| 229 | /* setup the master state. */ | ||
| 230 | master->bus_num = pdev->id; | ||
| 231 | master->num_chipselect = 16; | ||
| 232 | master->mode_bits = SPI_CS_HIGH; | ||
| 233 | master->setup = altera_spi_setup; | ||
| 234 | |||
| 235 | hw = spi_master_get_devdata(master); | ||
| 236 | platform_set_drvdata(pdev, hw); | ||
| 237 | |||
| 238 | /* setup the state for the bitbang driver */ | ||
| 239 | hw->bitbang.master = spi_master_get(master); | ||
| 240 | if (!hw->bitbang.master) | ||
| 241 | return err; | ||
| 242 | hw->bitbang.setup_transfer = altera_spi_setupxfer; | ||
| 243 | hw->bitbang.chipselect = altera_spi_chipsel; | ||
| 244 | hw->bitbang.txrx_bufs = altera_spi_txrx; | ||
| 245 | |||
| 246 | /* find and map our resources */ | ||
| 247 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 248 | if (!res) | ||
| 249 | goto exit_busy; | ||
| 250 | if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), | ||
| 251 | pdev->name)) | ||
| 252 | goto exit_busy; | ||
| 253 | hw->base = devm_ioremap_nocache(&pdev->dev, res->start, | ||
| 254 | resource_size(res)); | ||
| 255 | if (!hw->base) | ||
| 256 | goto exit_busy; | ||
| 257 | /* program defaults into the registers */ | ||
| 258 | hw->imr = 0; /* disable spi interrupts */ | ||
| 259 | writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); | ||
| 260 | writel(0, hw->base + ALTERA_SPI_STATUS); /* clear status reg */ | ||
| 261 | if (readl(hw->base + ALTERA_SPI_STATUS) & ALTERA_SPI_STATUS_RRDY_MSK) | ||
| 262 | readl(hw->base + ALTERA_SPI_RXDATA); /* flush rxdata */ | ||
| 263 | /* irq is optional */ | ||
| 264 | hw->irq = platform_get_irq(pdev, 0); | ||
| 265 | if (hw->irq >= 0) { | ||
| 266 | init_completion(&hw->done); | ||
| 267 | err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0, | ||
| 268 | pdev->name, hw); | ||
| 269 | if (err) | ||
| 270 | goto exit; | ||
| 271 | } | ||
| 272 | /* find platform data */ | ||
| 273 | if (!platp) | ||
| 274 | hw->bitbang.master->dev.of_node = pdev->dev.of_node; | ||
| 275 | |||
| 276 | /* register our spi controller */ | ||
| 277 | err = spi_bitbang_start(&hw->bitbang); | ||
| 278 | if (err) | ||
| 279 | goto exit; | ||
| 280 | dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq); | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | |||
| 284 | exit_busy: | ||
| 285 | err = -EBUSY; | ||
| 286 | exit: | ||
| 287 | platform_set_drvdata(pdev, NULL); | ||
| 288 | spi_master_put(master); | ||
| 289 | return err; | ||
| 290 | } | ||
| 291 | |||
| 292 | static int __devexit altera_spi_remove(struct platform_device *dev) | ||
| 293 | { | ||
| 294 | struct altera_spi *hw = platform_get_drvdata(dev); | ||
| 295 | struct spi_master *master = hw->bitbang.master; | ||
| 296 | |||
| 297 | spi_bitbang_stop(&hw->bitbang); | ||
| 298 | platform_set_drvdata(dev, NULL); | ||
| 299 | spi_master_put(master); | ||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | #ifdef CONFIG_OF | ||
| 304 | static const struct of_device_id altera_spi_match[] = { | ||
| 305 | { .compatible = "ALTR,spi-1.0", }, | ||
| 306 | {}, | ||
| 307 | }; | ||
| 308 | MODULE_DEVICE_TABLE(of, altera_spi_match); | ||
| 309 | #else /* CONFIG_OF */ | ||
| 310 | #define altera_spi_match NULL | ||
| 311 | #endif /* CONFIG_OF */ | ||
| 312 | |||
| 313 | static struct platform_driver altera_spi_driver = { | ||
| 314 | .probe = altera_spi_probe, | ||
| 315 | .remove = __devexit_p(altera_spi_remove), | ||
| 316 | .driver = { | ||
| 317 | .name = DRV_NAME, | ||
| 318 | .owner = THIS_MODULE, | ||
| 319 | .pm = NULL, | ||
| 320 | .of_match_table = altera_spi_match, | ||
| 321 | }, | ||
| 322 | }; | ||
| 323 | |||
| 324 | static int __init altera_spi_init(void) | ||
| 325 | { | ||
| 326 | return platform_driver_register(&altera_spi_driver); | ||
| 327 | } | ||
| 328 | module_init(altera_spi_init); | ||
| 329 | |||
| 330 | static void __exit altera_spi_exit(void) | ||
| 331 | { | ||
| 332 | platform_driver_unregister(&altera_spi_driver); | ||
| 333 | } | ||
| 334 | module_exit(altera_spi_exit); | ||
| 335 | |||
| 336 | MODULE_DESCRIPTION("Altera SPI driver"); | ||
| 337 | MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); | ||
| 338 | MODULE_LICENSE("GPL"); | ||
| 339 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 3f223511127b..a28462486df8 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c | |||
| @@ -425,6 +425,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) | |||
| 425 | struct bfin_spi_slave_data *chip = drv_data->cur_chip; | 425 | struct bfin_spi_slave_data *chip = drv_data->cur_chip; |
| 426 | struct spi_message *msg = drv_data->cur_msg; | 426 | struct spi_message *msg = drv_data->cur_msg; |
| 427 | int n_bytes = drv_data->n_bytes; | 427 | int n_bytes = drv_data->n_bytes; |
| 428 | int loop = 0; | ||
| 428 | 429 | ||
| 429 | /* wait until transfer finished. */ | 430 | /* wait until transfer finished. */ |
| 430 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | 431 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
| @@ -435,10 +436,15 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) | |||
| 435 | /* last read */ | 436 | /* last read */ |
| 436 | if (drv_data->rx) { | 437 | if (drv_data->rx) { |
| 437 | dev_dbg(&drv_data->pdev->dev, "last read\n"); | 438 | dev_dbg(&drv_data->pdev->dev, "last read\n"); |
| 438 | if (n_bytes == 2) | 439 | if (n_bytes % 2) { |
| 439 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | 440 | u16 *buf = (u16 *)drv_data->rx; |
| 440 | else if (n_bytes == 1) | 441 | for (loop = 0; loop < n_bytes / 2; loop++) |
| 441 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | 442 | *buf++ = read_RDBR(drv_data); |
| 443 | } else { | ||
| 444 | u8 *buf = (u8 *)drv_data->rx; | ||
| 445 | for (loop = 0; loop < n_bytes; loop++) | ||
| 446 | *buf++ = read_RDBR(drv_data); | ||
| 447 | } | ||
| 442 | drv_data->rx += n_bytes; | 448 | drv_data->rx += n_bytes; |
| 443 | } | 449 | } |
| 444 | 450 | ||
| @@ -458,29 +464,53 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) | |||
| 458 | if (drv_data->rx && drv_data->tx) { | 464 | if (drv_data->rx && drv_data->tx) { |
| 459 | /* duplex */ | 465 | /* duplex */ |
| 460 | dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n"); | 466 | dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n"); |
| 461 | if (drv_data->n_bytes == 2) { | 467 | if (n_bytes % 2) { |
| 462 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | 468 | u16 *buf = (u16 *)drv_data->rx; |
| 463 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 469 | u16 *buf2 = (u16 *)drv_data->tx; |
| 464 | } else if (drv_data->n_bytes == 1) { | 470 | for (loop = 0; loop < n_bytes / 2; loop++) { |
| 465 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | 471 | *buf++ = read_RDBR(drv_data); |
| 466 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 472 | write_TDBR(drv_data, *buf2++); |
| 473 | } | ||
| 474 | } else { | ||
| 475 | u8 *buf = (u8 *)drv_data->rx; | ||
| 476 | u8 *buf2 = (u8 *)drv_data->tx; | ||
| 477 | for (loop = 0; loop < n_bytes; loop++) { | ||
| 478 | *buf++ = read_RDBR(drv_data); | ||
| 479 | write_TDBR(drv_data, *buf2++); | ||
| 480 | } | ||
| 467 | } | 481 | } |
| 468 | } else if (drv_data->rx) { | 482 | } else if (drv_data->rx) { |
| 469 | /* read */ | 483 | /* read */ |
| 470 | dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n"); | 484 | dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n"); |
| 471 | if (drv_data->n_bytes == 2) | 485 | if (n_bytes % 2) { |
| 472 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | 486 | u16 *buf = (u16 *)drv_data->rx; |
| 473 | else if (drv_data->n_bytes == 1) | 487 | for (loop = 0; loop < n_bytes / 2; loop++) { |
| 474 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | 488 | *buf++ = read_RDBR(drv_data); |
| 475 | write_TDBR(drv_data, chip->idle_tx_val); | 489 | write_TDBR(drv_data, chip->idle_tx_val); |
| 490 | } | ||
| 491 | } else { | ||
| 492 | u8 *buf = (u8 *)drv_data->rx; | ||
| 493 | for (loop = 0; loop < n_bytes; loop++) { | ||
| 494 | *buf++ = read_RDBR(drv_data); | ||
| 495 | write_TDBR(drv_data, chip->idle_tx_val); | ||
| 496 | } | ||
| 497 | } | ||
| 476 | } else if (drv_data->tx) { | 498 | } else if (drv_data->tx) { |
| 477 | /* write */ | 499 | /* write */ |
| 478 | dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n"); | 500 | dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n"); |
| 479 | bfin_spi_dummy_read(drv_data); | 501 | if (n_bytes % 2) { |
| 480 | if (drv_data->n_bytes == 2) | 502 | u16 *buf = (u16 *)drv_data->tx; |
| 481 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 503 | for (loop = 0; loop < n_bytes / 2; loop++) { |
| 482 | else if (drv_data->n_bytes == 1) | 504 | read_RDBR(drv_data); |
| 483 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 505 | write_TDBR(drv_data, *buf++); |
| 506 | } | ||
| 507 | } else { | ||
| 508 | u8 *buf = (u8 *)drv_data->tx; | ||
| 509 | for (loop = 0; loop < n_bytes; loop++) { | ||
| 510 | read_RDBR(drv_data); | ||
| 511 | write_TDBR(drv_data, *buf++); | ||
| 512 | } | ||
| 513 | } | ||
| 484 | } | 514 | } |
| 485 | 515 | ||
| 486 | if (drv_data->tx) | 516 | if (drv_data->tx) |
| @@ -623,6 +653,7 @@ static void bfin_spi_pump_transfers(unsigned long data) | |||
| 623 | message->state = bfin_spi_next_transfer(drv_data); | 653 | message->state = bfin_spi_next_transfer(drv_data); |
| 624 | /* Schedule next transfer tasklet */ | 654 | /* Schedule next transfer tasklet */ |
| 625 | tasklet_schedule(&drv_data->pump_transfers); | 655 | tasklet_schedule(&drv_data->pump_transfers); |
| 656 | return; | ||
| 626 | } | 657 | } |
| 627 | 658 | ||
| 628 | if (transfer->tx_buf != NULL) { | 659 | if (transfer->tx_buf != NULL) { |
| @@ -651,16 +682,16 @@ static void bfin_spi_pump_transfers(unsigned long data) | |||
| 651 | 682 | ||
| 652 | /* Bits per word setup */ | 683 | /* Bits per word setup */ |
| 653 | bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word; | 684 | bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word; |
| 654 | if (bits_per_word == 8) { | 685 | if ((bits_per_word > 0) && (bits_per_word % 16 == 0)) { |
| 655 | drv_data->n_bytes = 1; | 686 | drv_data->n_bytes = bits_per_word/8; |
| 656 | drv_data->len = transfer->len; | ||
| 657 | cr_width = 0; | ||
| 658 | drv_data->ops = &bfin_bfin_spi_transfer_ops_u8; | ||
| 659 | } else if (bits_per_word == 16) { | ||
| 660 | drv_data->n_bytes = 2; | ||
| 661 | drv_data->len = (transfer->len) >> 1; | 687 | drv_data->len = (transfer->len) >> 1; |
| 662 | cr_width = BIT_CTL_WORDSIZE; | 688 | cr_width = BIT_CTL_WORDSIZE; |
| 663 | drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; | 689 | drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; |
| 690 | } else if ((bits_per_word > 0) && (bits_per_word % 8 == 0)) { | ||
| 691 | drv_data->n_bytes = bits_per_word/8; | ||
| 692 | drv_data->len = transfer->len; | ||
| 693 | cr_width = 0; | ||
| 694 | drv_data->ops = &bfin_bfin_spi_transfer_ops_u8; | ||
| 664 | } else { | 695 | } else { |
| 665 | dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n"); | 696 | dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n"); |
| 666 | message->status = -EINVAL; | 697 | message->status = -EINVAL; |
| @@ -815,10 +846,19 @@ static void bfin_spi_pump_transfers(unsigned long data) | |||
| 815 | if (drv_data->tx == NULL) | 846 | if (drv_data->tx == NULL) |
| 816 | write_TDBR(drv_data, chip->idle_tx_val); | 847 | write_TDBR(drv_data, chip->idle_tx_val); |
| 817 | else { | 848 | else { |
| 818 | if (bits_per_word == 8) | 849 | int loop; |
| 819 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 850 | if (bits_per_word % 16 == 0) { |
| 820 | else | 851 | u16 *buf = (u16 *)drv_data->tx; |
| 821 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 852 | for (loop = 0; loop < bits_per_word / 16; |
| 853 | loop++) { | ||
| 854 | write_TDBR(drv_data, *buf++); | ||
| 855 | } | ||
| 856 | } else if (bits_per_word % 8 == 0) { | ||
| 857 | u8 *buf = (u8 *)drv_data->tx; | ||
| 858 | for (loop = 0; loop < bits_per_word / 8; loop++) | ||
| 859 | write_TDBR(drv_data, *buf++); | ||
| 860 | } | ||
| 861 | |||
| 822 | drv_data->tx += drv_data->n_bytes; | 862 | drv_data->tx += drv_data->n_bytes; |
| 823 | } | 863 | } |
| 824 | 864 | ||
| @@ -1031,7 +1071,7 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
| 1031 | chip->ctl_reg &= bfin_ctl_reg; | 1071 | chip->ctl_reg &= bfin_ctl_reg; |
| 1032 | } | 1072 | } |
| 1033 | 1073 | ||
| 1034 | if (spi->bits_per_word != 8 && spi->bits_per_word != 16) { | 1074 | if (spi->bits_per_word % 8) { |
| 1035 | dev_err(&spi->dev, "%d bits_per_word is not supported\n", | 1075 | dev_err(&spi->dev, "%d bits_per_word is not supported\n", |
| 1036 | spi->bits_per_word); | 1076 | spi->bits_per_word); |
| 1037 | goto error; | 1077 | goto error; |
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 8b55724d5f39..14a63f6010d1 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c | |||
| @@ -259,10 +259,6 @@ static void bitbang_work(struct work_struct *work) | |||
| 259 | struct spi_bitbang *bitbang = | 259 | struct spi_bitbang *bitbang = |
| 260 | container_of(work, struct spi_bitbang, work); | 260 | container_of(work, struct spi_bitbang, work); |
| 261 | unsigned long flags; | 261 | unsigned long flags; |
| 262 | int (*setup_transfer)(struct spi_device *, | ||
| 263 | struct spi_transfer *); | ||
| 264 | |||
| 265 | setup_transfer = bitbang->setup_transfer; | ||
| 266 | 262 | ||
| 267 | spin_lock_irqsave(&bitbang->lock, flags); | 263 | spin_lock_irqsave(&bitbang->lock, flags); |
| 268 | bitbang->busy = 1; | 264 | bitbang->busy = 1; |
| @@ -300,11 +296,7 @@ static void bitbang_work(struct work_struct *work) | |||
| 300 | 296 | ||
| 301 | /* init (-1) or override (1) transfer params */ | 297 | /* init (-1) or override (1) transfer params */ |
| 302 | if (do_setup != 0) { | 298 | if (do_setup != 0) { |
| 303 | if (!setup_transfer) { | 299 | status = bitbang->setup_transfer(spi, t); |
| 304 | status = -ENOPROTOOPT; | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | status = setup_transfer(spi, t); | ||
| 308 | if (status < 0) | 300 | if (status < 0) |
| 309 | break; | 301 | break; |
| 310 | if (do_setup == -1) | 302 | if (do_setup == -1) |
| @@ -465,6 +457,9 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) | |||
| 465 | } | 457 | } |
| 466 | } else if (!bitbang->master->setup) | 458 | } else if (!bitbang->master->setup) |
| 467 | return -EINVAL; | 459 | return -EINVAL; |
| 460 | if (bitbang->master->transfer == spi_bitbang_transfer && | ||
| 461 | !bitbang->setup_transfer) | ||
| 462 | return -EINVAL; | ||
| 468 | 463 | ||
| 469 | /* this task is the only thing to touch the SPI bits */ | 464 | /* this task is the only thing to touch the SPI bits */ |
| 470 | bitbang->busy = 0; | 465 | bitbang->busy = 0; |
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 1cf9d5faabf4..69d6dba67c19 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c | |||
| @@ -174,7 +174,7 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin, | |||
| 174 | #define SPI_IMX2_3_CTRL 0x08 | 174 | #define SPI_IMX2_3_CTRL 0x08 |
| 175 | #define SPI_IMX2_3_CTRL_ENABLE (1 << 0) | 175 | #define SPI_IMX2_3_CTRL_ENABLE (1 << 0) |
| 176 | #define SPI_IMX2_3_CTRL_XCH (1 << 2) | 176 | #define SPI_IMX2_3_CTRL_XCH (1 << 2) |
| 177 | #define SPI_IMX2_3_CTRL_MODE(cs) (1 << ((cs) + 4)) | 177 | #define SPI_IMX2_3_CTRL_MODE_MASK (0xf << 4) |
| 178 | #define SPI_IMX2_3_CTRL_POSTDIV_OFFSET 8 | 178 | #define SPI_IMX2_3_CTRL_POSTDIV_OFFSET 8 |
| 179 | #define SPI_IMX2_3_CTRL_PREDIV_OFFSET 12 | 179 | #define SPI_IMX2_3_CTRL_PREDIV_OFFSET 12 |
| 180 | #define SPI_IMX2_3_CTRL_CS(cs) ((cs) << 18) | 180 | #define SPI_IMX2_3_CTRL_CS(cs) ((cs) << 18) |
| @@ -253,8 +253,14 @@ static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx, | |||
| 253 | { | 253 | { |
| 254 | u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0; | 254 | u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0; |
| 255 | 255 | ||
| 256 | /* set master mode */ | 256 | /* |
| 257 | ctrl |= SPI_IMX2_3_CTRL_MODE(config->cs); | 257 | * The hardware seems to have a race condition when changing modes. The |
| 258 | * current assumption is that the selection of the channel arrives | ||
| 259 | * earlier in the hardware than the mode bits when they are written at | ||
| 260 | * the same time. | ||
| 261 | * So set master mode for all channels as we do not support slave mode. | ||
| 262 | */ | ||
| 263 | ctrl |= SPI_IMX2_3_CTRL_MODE_MASK; | ||
| 258 | 264 | ||
| 259 | /* set clock speed */ | 265 | /* set clock speed */ |
| 260 | ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz); | 266 | ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz); |
diff --git a/drivers/spi/spi_oc_tiny.c b/drivers/spi/spi_oc_tiny.c new file mode 100644 index 000000000000..f1bde66cea19 --- /dev/null +++ b/drivers/spi/spi_oc_tiny.c | |||
| @@ -0,0 +1,425 @@ | |||
| 1 | /* | ||
| 2 | * OpenCores tiny SPI master driver | ||
| 3 | * | ||
| 4 | * http://opencores.org/project,tiny_spi | ||
| 5 | * | ||
| 6 | * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw> | ||
| 7 | * | ||
| 8 | * Based on spi_s3c24xx.c, which is: | ||
| 9 | * Copyright (c) 2006 Ben Dooks | ||
| 10 | * Copyright (c) 2006 Simtec Electronics | ||
| 11 | * Ben Dooks <ben@simtec.co.uk> | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or modify | ||
| 14 | * it under the terms of the GNU General Public License version 2 as | ||
| 15 | * published by the Free Software Foundation. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/errno.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/spi/spi.h> | ||
| 23 | #include <linux/spi/spi_bitbang.h> | ||
| 24 | #include <linux/spi/spi_oc_tiny.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | #include <linux/gpio.h> | ||
| 27 | #include <linux/of.h> | ||
| 28 | |||
| 29 | #define DRV_NAME "spi_oc_tiny" | ||
| 30 | |||
| 31 | #define TINY_SPI_RXDATA 0 | ||
| 32 | #define TINY_SPI_TXDATA 4 | ||
| 33 | #define TINY_SPI_STATUS 8 | ||
| 34 | #define TINY_SPI_CONTROL 12 | ||
| 35 | #define TINY_SPI_BAUD 16 | ||
| 36 | |||
| 37 | #define TINY_SPI_STATUS_TXE 0x1 | ||
| 38 | #define TINY_SPI_STATUS_TXR 0x2 | ||
| 39 | |||
| 40 | struct tiny_spi { | ||
| 41 | /* bitbang has to be first */ | ||
| 42 | struct spi_bitbang bitbang; | ||
| 43 | struct completion done; | ||
| 44 | |||
| 45 | void __iomem *base; | ||
| 46 | int irq; | ||
| 47 | unsigned int freq; | ||
| 48 | unsigned int baudwidth; | ||
| 49 | unsigned int baud; | ||
| 50 | unsigned int speed_hz; | ||
| 51 | unsigned int mode; | ||
| 52 | unsigned int len; | ||
| 53 | unsigned int txc, rxc; | ||
| 54 | const u8 *txp; | ||
| 55 | u8 *rxp; | ||
| 56 | unsigned int gpio_cs_count; | ||
| 57 | int *gpio_cs; | ||
| 58 | }; | ||
| 59 | |||
| 60 | static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev) | ||
| 61 | { | ||
| 62 | return spi_master_get_devdata(sdev->master); | ||
| 63 | } | ||
| 64 | |||
| 65 | static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz) | ||
| 66 | { | ||
| 67 | struct tiny_spi *hw = tiny_spi_to_hw(spi); | ||
| 68 | |||
| 69 | return min(DIV_ROUND_UP(hw->freq, hz * 2), (1U << hw->baudwidth)) - 1; | ||
| 70 | } | ||
| 71 | |||
| 72 | static void tiny_spi_chipselect(struct spi_device *spi, int is_active) | ||
| 73 | { | ||
| 74 | struct tiny_spi *hw = tiny_spi_to_hw(spi); | ||
| 75 | |||
| 76 | if (hw->gpio_cs_count) { | ||
| 77 | gpio_set_value(hw->gpio_cs[spi->chip_select], | ||
| 78 | (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | static int tiny_spi_setup_transfer(struct spi_device *spi, | ||
| 83 | struct spi_transfer *t) | ||
| 84 | { | ||
| 85 | struct tiny_spi *hw = tiny_spi_to_hw(spi); | ||
| 86 | unsigned int baud = hw->baud; | ||
| 87 | |||
| 88 | if (t) { | ||
| 89 | if (t->speed_hz && t->speed_hz != hw->speed_hz) | ||
| 90 | baud = tiny_spi_baud(spi, t->speed_hz); | ||
| 91 | } | ||
| 92 | writel(baud, hw->base + TINY_SPI_BAUD); | ||
| 93 | writel(hw->mode, hw->base + TINY_SPI_CONTROL); | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | static int tiny_spi_setup(struct spi_device *spi) | ||
| 98 | { | ||
| 99 | struct tiny_spi *hw = tiny_spi_to_hw(spi); | ||
| 100 | |||
| 101 | if (spi->max_speed_hz != hw->speed_hz) { | ||
| 102 | hw->speed_hz = spi->max_speed_hz; | ||
| 103 | hw->baud = tiny_spi_baud(spi, hw->speed_hz); | ||
| 104 | } | ||
| 105 | hw->mode = spi->mode & (SPI_CPOL | SPI_CPHA); | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | static inline void tiny_spi_wait_txr(struct tiny_spi *hw) | ||
| 110 | { | ||
| 111 | while (!(readb(hw->base + TINY_SPI_STATUS) & | ||
| 112 | TINY_SPI_STATUS_TXR)) | ||
| 113 | cpu_relax(); | ||
| 114 | } | ||
| 115 | |||
| 116 | static inline void tiny_spi_wait_txe(struct tiny_spi *hw) | ||
| 117 | { | ||
| 118 | while (!(readb(hw->base + TINY_SPI_STATUS) & | ||
| 119 | TINY_SPI_STATUS_TXE)) | ||
| 120 | cpu_relax(); | ||
| 121 | } | ||
| 122 | |||
| 123 | static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) | ||
| 124 | { | ||
| 125 | struct tiny_spi *hw = tiny_spi_to_hw(spi); | ||
| 126 | const u8 *txp = t->tx_buf; | ||
| 127 | u8 *rxp = t->rx_buf; | ||
| 128 | unsigned int i; | ||
| 129 | |||
| 130 | if (hw->irq >= 0) { | ||
| 131 | /* use intrrupt driven data transfer */ | ||
| 132 | hw->len = t->len; | ||
| 133 | hw->txp = t->tx_buf; | ||
| 134 | hw->rxp = t->rx_buf; | ||
| 135 | hw->txc = 0; | ||
| 136 | hw->rxc = 0; | ||
| 137 | |||
| 138 | /* send the first byte */ | ||
| 139 | if (t->len > 1) { | ||
| 140 | writeb(hw->txp ? *hw->txp++ : 0, | ||
| 141 | hw->base + TINY_SPI_TXDATA); | ||
| 142 | hw->txc++; | ||
| 143 | writeb(hw->txp ? *hw->txp++ : 0, | ||
| 144 | hw->base + TINY_SPI_TXDATA); | ||
| 145 | hw->txc++; | ||
| 146 | writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS); | ||
| 147 | } else { | ||
| 148 | writeb(hw->txp ? *hw->txp++ : 0, | ||
| 149 | hw->base + TINY_SPI_TXDATA); | ||
| 150 | hw->txc++; | ||
| 151 | writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS); | ||
| 152 | } | ||
| 153 | |||
| 154 | wait_for_completion(&hw->done); | ||
| 155 | } else if (txp && rxp) { | ||
| 156 | /* we need to tighten the transfer loop */ | ||
| 157 | writeb(*txp++, hw->base + TINY_SPI_TXDATA); | ||
| 158 | if (t->len > 1) { | ||
| 159 | writeb(*txp++, hw->base + TINY_SPI_TXDATA); | ||
| 160 | for (i = 2; i < t->len; i++) { | ||
| 161 | u8 rx, tx = *txp++; | ||
| 162 | tiny_spi_wait_txr(hw); | ||
| 163 | rx = readb(hw->base + TINY_SPI_TXDATA); | ||
| 164 | writeb(tx, hw->base + TINY_SPI_TXDATA); | ||
| 165 | *rxp++ = rx; | ||
| 166 | } | ||
| 167 | tiny_spi_wait_txr(hw); | ||
| 168 | *rxp++ = readb(hw->base + TINY_SPI_TXDATA); | ||
| 169 | } | ||
| 170 | tiny_spi_wait_txe(hw); | ||
| 171 | *rxp++ = readb(hw->base + TINY_SPI_RXDATA); | ||
| 172 | } else if (rxp) { | ||
| 173 | writeb(0, hw->base + TINY_SPI_TXDATA); | ||
| 174 | if (t->len > 1) { | ||
| 175 | writeb(0, | ||
| 176 | hw->base + TINY_SPI_TXDATA); | ||
| 177 | for (i = 2; i < t->len; i++) { | ||
| 178 | u8 rx; | ||
| 179 | tiny_spi_wait_txr(hw); | ||
| 180 | rx = readb(hw->base + TINY_SPI_TXDATA); | ||
| 181 | writeb(0, hw->base + TINY_SPI_TXDATA); | ||
| 182 | *rxp++ = rx; | ||
| 183 | } | ||
| 184 | tiny_spi_wait_txr(hw); | ||
| 185 | *rxp++ = readb(hw->base + TINY_SPI_TXDATA); | ||
| 186 | } | ||
| 187 | tiny_spi_wait_txe(hw); | ||
| 188 | *rxp++ = readb(hw->base + TINY_SPI_RXDATA); | ||
| 189 | } else if (txp) { | ||
| 190 | writeb(*txp++, hw->base + TINY_SPI_TXDATA); | ||
| 191 | if (t->len > 1) { | ||
| 192 | writeb(*txp++, hw->base + TINY_SPI_TXDATA); | ||
| 193 | for (i = 2; i < t->len; i++) { | ||
| 194 | u8 tx = *txp++; | ||
| 195 | tiny_spi_wait_txr(hw); | ||
| 196 | writeb(tx, hw->base + TINY_SPI_TXDATA); | ||
| 197 | } | ||
| 198 | } | ||
| 199 | tiny_spi_wait_txe(hw); | ||
| 200 | } else { | ||
| 201 | writeb(0, hw->base + TINY_SPI_TXDATA); | ||
| 202 | if (t->len > 1) { | ||
| 203 | writeb(0, hw->base + TINY_SPI_TXDATA); | ||
| 204 | for (i = 2; i < t->len; i++) { | ||
| 205 | tiny_spi_wait_txr(hw); | ||
| 206 | writeb(0, hw->base + TINY_SPI_TXDATA); | ||
| 207 | } | ||
| 208 | } | ||
| 209 | tiny_spi_wait_txe(hw); | ||
| 210 | } | ||
| 211 | return t->len; | ||
| 212 | } | ||
| 213 | |||
| 214 | static irqreturn_t tiny_spi_irq(int irq, void *dev) | ||
| 215 | { | ||
| 216 | struct tiny_spi *hw = dev; | ||
| 217 | |||
| 218 | writeb(0, hw->base + TINY_SPI_STATUS); | ||
| 219 | if (hw->rxc + 1 == hw->len) { | ||
| 220 | if (hw->rxp) | ||
| 221 | *hw->rxp++ = readb(hw->base + TINY_SPI_RXDATA); | ||
| 222 | hw->rxc++; | ||
| 223 | complete(&hw->done); | ||
| 224 | } else { | ||
| 225 | if (hw->rxp) | ||
| 226 | *hw->rxp++ = readb(hw->base + TINY_SPI_TXDATA); | ||
| 227 | hw->rxc++; | ||
| 228 | if (hw->txc < hw->len) { | ||
| 229 | writeb(hw->txp ? *hw->txp++ : 0, | ||
| 230 | hw->base + TINY_SPI_TXDATA); | ||
| 231 | hw->txc++; | ||
| 232 | writeb(TINY_SPI_STATUS_TXR, | ||
| 233 | hw->base + TINY_SPI_STATUS); | ||
| 234 | } else { | ||
| 235 | writeb(TINY_SPI_STATUS_TXE, | ||
| 236 | hw->base + TINY_SPI_STATUS); | ||
| 237 | } | ||
| 238 | } | ||
| 239 | return IRQ_HANDLED; | ||
| 240 | } | ||
| 241 | |||
| 242 | #ifdef CONFIG_OF | ||
| 243 | #include <linux/of_gpio.h> | ||
| 244 | |||
| 245 | static int __devinit tiny_spi_of_probe(struct platform_device *pdev) | ||
| 246 | { | ||
| 247 | struct tiny_spi *hw = platform_get_drvdata(pdev); | ||
| 248 | struct device_node *np = pdev->dev.of_node; | ||
| 249 | unsigned int i; | ||
| 250 | const __be32 *val; | ||
| 251 | int len; | ||
| 252 | |||
| 253 | if (!np) | ||
| 254 | return 0; | ||
| 255 | hw->gpio_cs_count = of_gpio_count(np); | ||
| 256 | if (hw->gpio_cs_count) { | ||
| 257 | hw->gpio_cs = devm_kzalloc(&pdev->dev, | ||
| 258 | hw->gpio_cs_count * sizeof(unsigned int), | ||
| 259 | GFP_KERNEL); | ||
| 260 | if (!hw->gpio_cs) | ||
| 261 | return -ENOMEM; | ||
| 262 | } | ||
| 263 | for (i = 0; i < hw->gpio_cs_count; i++) { | ||
| 264 | hw->gpio_cs[i] = of_get_gpio_flags(np, i, NULL); | ||
| 265 | if (hw->gpio_cs[i] < 0) | ||
| 266 | return -ENODEV; | ||
| 267 | } | ||
| 268 | hw->bitbang.master->dev.of_node = pdev->dev.of_node; | ||
| 269 | val = of_get_property(pdev->dev.of_node, | ||
| 270 | "clock-frequency", &len); | ||
| 271 | if (val && len >= sizeof(__be32)) | ||
| 272 | hw->freq = be32_to_cpup(val); | ||
| 273 | val = of_get_property(pdev->dev.of_node, "baud-width", &len); | ||
| 274 | if (val && len >= sizeof(__be32)) | ||
| 275 | hw->baudwidth = be32_to_cpup(val); | ||
| 276 | return 0; | ||
| 277 | } | ||
| 278 | #else /* !CONFIG_OF */ | ||
| 279 | static int __devinit tiny_spi_of_probe(struct platform_device *pdev) | ||
| 280 | { | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | #endif /* CONFIG_OF */ | ||
| 284 | |||
| 285 | static int __devinit tiny_spi_probe(struct platform_device *pdev) | ||
| 286 | { | ||
| 287 | struct tiny_spi_platform_data *platp = pdev->dev.platform_data; | ||
| 288 | struct tiny_spi *hw; | ||
| 289 | struct spi_master *master; | ||
| 290 | struct resource *res; | ||
| 291 | unsigned int i; | ||
| 292 | int err = -ENODEV; | ||
| 293 | |||
| 294 | master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi)); | ||
| 295 | if (!master) | ||
| 296 | return err; | ||
| 297 | |||
| 298 | /* setup the master state. */ | ||
| 299 | master->bus_num = pdev->id; | ||
| 300 | master->num_chipselect = 255; | ||
| 301 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | ||
| 302 | master->setup = tiny_spi_setup; | ||
| 303 | |||
| 304 | hw = spi_master_get_devdata(master); | ||
| 305 | platform_set_drvdata(pdev, hw); | ||
| 306 | |||
| 307 | /* setup the state for the bitbang driver */ | ||
| 308 | hw->bitbang.master = spi_master_get(master); | ||
| 309 | if (!hw->bitbang.master) | ||
| 310 | return err; | ||
| 311 | hw->bitbang.setup_transfer = tiny_spi_setup_transfer; | ||
| 312 | hw->bitbang.chipselect = tiny_spi_chipselect; | ||
| 313 | hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs; | ||
| 314 | |||
| 315 | /* find and map our resources */ | ||
| 316 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 317 | if (!res) | ||
| 318 | goto exit_busy; | ||
| 319 | if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), | ||
| 320 | pdev->name)) | ||
| 321 | goto exit_busy; | ||
| 322 | hw->base = devm_ioremap_nocache(&pdev->dev, res->start, | ||
| 323 | resource_size(res)); | ||
| 324 | if (!hw->base) | ||
| 325 | goto exit_busy; | ||
| 326 | /* irq is optional */ | ||
| 327 | hw->irq = platform_get_irq(pdev, 0); | ||
| 328 | if (hw->irq >= 0) { | ||
| 329 | init_completion(&hw->done); | ||
| 330 | err = devm_request_irq(&pdev->dev, hw->irq, tiny_spi_irq, 0, | ||
| 331 | pdev->name, hw); | ||
| 332 | if (err) | ||
| 333 | goto exit; | ||
| 334 | } | ||
| 335 | /* find platform data */ | ||
| 336 | if (platp) { | ||
| 337 | hw->gpio_cs_count = platp->gpio_cs_count; | ||
| 338 | hw->gpio_cs = platp->gpio_cs; | ||
| 339 | if (platp->gpio_cs_count && !platp->gpio_cs) | ||
| 340 | goto exit_busy; | ||
| 341 | hw->freq = platp->freq; | ||
| 342 | hw->baudwidth = platp->baudwidth; | ||
| 343 | } else { | ||
| 344 | err = tiny_spi_of_probe(pdev); | ||
| 345 | if (err) | ||
| 346 | goto exit; | ||
| 347 | } | ||
| 348 | for (i = 0; i < hw->gpio_cs_count; i++) { | ||
| 349 | err = gpio_request(hw->gpio_cs[i], dev_name(&pdev->dev)); | ||
| 350 | if (err) | ||
| 351 | goto exit_gpio; | ||
| 352 | gpio_direction_output(hw->gpio_cs[i], 1); | ||
| 353 | } | ||
| 354 | hw->bitbang.master->num_chipselect = max(1U, hw->gpio_cs_count); | ||
| 355 | |||
| 356 | /* register our spi controller */ | ||
| 357 | err = spi_bitbang_start(&hw->bitbang); | ||
| 358 | if (err) | ||
| 359 | goto exit; | ||
| 360 | dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq); | ||
| 361 | |||
| 362 | return 0; | ||
| 363 | |||
| 364 | exit_gpio: | ||
| 365 | while (i-- > 0) | ||
| 366 | gpio_free(hw->gpio_cs[i]); | ||
| 367 | exit_busy: | ||
| 368 | err = -EBUSY; | ||
| 369 | exit: | ||
| 370 | platform_set_drvdata(pdev, NULL); | ||
| 371 | spi_master_put(master); | ||
| 372 | return err; | ||
| 373 | } | ||
| 374 | |||
| 375 | static int __devexit tiny_spi_remove(struct platform_device *pdev) | ||
| 376 | { | ||
| 377 | struct tiny_spi *hw = platform_get_drvdata(pdev); | ||
| 378 | struct spi_master *master = hw->bitbang.master; | ||
| 379 | unsigned int i; | ||
| 380 | |||
| 381 | spi_bitbang_stop(&hw->bitbang); | ||
| 382 | for (i = 0; i < hw->gpio_cs_count; i++) | ||
| 383 | gpio_free(hw->gpio_cs[i]); | ||
| 384 | platform_set_drvdata(pdev, NULL); | ||
| 385 | spi_master_put(master); | ||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | |||
| 389 | #ifdef CONFIG_OF | ||
| 390 | static const struct of_device_id tiny_spi_match[] = { | ||
| 391 | { .compatible = "opencores,tiny-spi-rtlsvn2", }, | ||
| 392 | {}, | ||
| 393 | }; | ||
| 394 | MODULE_DEVICE_TABLE(of, tiny_spi_match); | ||
| 395 | #else /* CONFIG_OF */ | ||
| 396 | #define tiny_spi_match NULL | ||
| 397 | #endif /* CONFIG_OF */ | ||
| 398 | |||
| 399 | static struct platform_driver tiny_spi_driver = { | ||
| 400 | .probe = tiny_spi_probe, | ||
| 401 | .remove = __devexit_p(tiny_spi_remove), | ||
| 402 | .driver = { | ||
| 403 | .name = DRV_NAME, | ||
| 404 | .owner = THIS_MODULE, | ||
| 405 | .pm = NULL, | ||
| 406 | .of_match_table = tiny_spi_match, | ||
| 407 | }, | ||
| 408 | }; | ||
| 409 | |||
| 410 | static int __init tiny_spi_init(void) | ||
| 411 | { | ||
| 412 | return platform_driver_register(&tiny_spi_driver); | ||
| 413 | } | ||
| 414 | module_init(tiny_spi_init); | ||
| 415 | |||
| 416 | static void __exit tiny_spi_exit(void) | ||
| 417 | { | ||
| 418 | platform_driver_unregister(&tiny_spi_driver); | ||
| 419 | } | ||
| 420 | module_exit(tiny_spi_exit); | ||
| 421 | |||
| 422 | MODULE_DESCRIPTION("OpenCores tiny SPI driver"); | ||
| 423 | MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); | ||
| 424 | MODULE_LICENSE("GPL"); | ||
| 425 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/spi/spi_sh.c b/drivers/spi/spi_sh.c new file mode 100644 index 000000000000..869a07d375d6 --- /dev/null +++ b/drivers/spi/spi_sh.c | |||
| @@ -0,0 +1,543 @@ | |||
| 1 | /* | ||
| 2 | * SH SPI bus driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Renesas Solutions Corp. | ||
| 5 | * | ||
| 6 | * Based on pxa2xx_spi.c: | ||
| 7 | * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; version 2 of the License. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <linux/sched.h> | ||
| 27 | #include <linux/errno.h> | ||
| 28 | #include <linux/timer.h> | ||
| 29 | #include <linux/delay.h> | ||
| 30 | #include <linux/list.h> | ||
| 31 | #include <linux/workqueue.h> | ||
| 32 | #include <linux/interrupt.h> | ||
| 33 | #include <linux/platform_device.h> | ||
| 34 | #include <linux/io.h> | ||
| 35 | #include <linux/spi/spi.h> | ||
| 36 | |||
| 37 | #define SPI_SH_TBR 0x00 | ||
| 38 | #define SPI_SH_RBR 0x00 | ||
| 39 | #define SPI_SH_CR1 0x08 | ||
| 40 | #define SPI_SH_CR2 0x10 | ||
| 41 | #define SPI_SH_CR3 0x18 | ||
| 42 | #define SPI_SH_CR4 0x20 | ||
| 43 | #define SPI_SH_CR5 0x28 | ||
| 44 | |||
| 45 | /* CR1 */ | ||
| 46 | #define SPI_SH_TBE 0x80 | ||
| 47 | #define SPI_SH_TBF 0x40 | ||
| 48 | #define SPI_SH_RBE 0x20 | ||
| 49 | #define SPI_SH_RBF 0x10 | ||
| 50 | #define SPI_SH_PFONRD 0x08 | ||
| 51 | #define SPI_SH_SSDB 0x04 | ||
| 52 | #define SPI_SH_SSD 0x02 | ||
| 53 | #define SPI_SH_SSA 0x01 | ||
| 54 | |||
| 55 | /* CR2 */ | ||
| 56 | #define SPI_SH_RSTF 0x80 | ||
| 57 | #define SPI_SH_LOOPBK 0x40 | ||
| 58 | #define SPI_SH_CPOL 0x20 | ||
| 59 | #define SPI_SH_CPHA 0x10 | ||
| 60 | #define SPI_SH_L1M0 0x08 | ||
| 61 | |||
| 62 | /* CR3 */ | ||
| 63 | #define SPI_SH_MAX_BYTE 0xFF | ||
| 64 | |||
| 65 | /* CR4 */ | ||
| 66 | #define SPI_SH_TBEI 0x80 | ||
| 67 | #define SPI_SH_TBFI 0x40 | ||
| 68 | #define SPI_SH_RBEI 0x20 | ||
| 69 | #define SPI_SH_RBFI 0x10 | ||
| 70 | #define SPI_SH_WPABRT 0x04 | ||
| 71 | #define SPI_SH_SSS 0x01 | ||
| 72 | |||
| 73 | /* CR8 */ | ||
| 74 | #define SPI_SH_P1L0 0x80 | ||
| 75 | #define SPI_SH_PP1L0 0x40 | ||
| 76 | #define SPI_SH_MUXI 0x20 | ||
| 77 | #define SPI_SH_MUXIRQ 0x10 | ||
| 78 | |||
| 79 | #define SPI_SH_FIFO_SIZE 32 | ||
| 80 | #define SPI_SH_SEND_TIMEOUT (3 * HZ) | ||
| 81 | #define SPI_SH_RECEIVE_TIMEOUT (HZ >> 3) | ||
| 82 | |||
| 83 | #undef DEBUG | ||
| 84 | |||
| 85 | struct spi_sh_data { | ||
| 86 | void __iomem *addr; | ||
| 87 | int irq; | ||
| 88 | struct spi_master *master; | ||
| 89 | struct list_head queue; | ||
| 90 | struct workqueue_struct *workqueue; | ||
| 91 | struct work_struct ws; | ||
| 92 | unsigned long cr1; | ||
| 93 | wait_queue_head_t wait; | ||
| 94 | spinlock_t lock; | ||
| 95 | }; | ||
| 96 | |||
| 97 | static void spi_sh_write(struct spi_sh_data *ss, unsigned long data, | ||
| 98 | unsigned long offset) | ||
| 99 | { | ||
| 100 | writel(data, ss->addr + offset); | ||
| 101 | } | ||
| 102 | |||
| 103 | static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset) | ||
| 104 | { | ||
| 105 | return readl(ss->addr + offset); | ||
| 106 | } | ||
| 107 | |||
| 108 | static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val, | ||
| 109 | unsigned long offset) | ||
| 110 | { | ||
| 111 | unsigned long tmp; | ||
| 112 | |||
| 113 | tmp = spi_sh_read(ss, offset); | ||
| 114 | tmp |= val; | ||
| 115 | spi_sh_write(ss, tmp, offset); | ||
| 116 | } | ||
| 117 | |||
| 118 | static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val, | ||
| 119 | unsigned long offset) | ||
| 120 | { | ||
| 121 | unsigned long tmp; | ||
| 122 | |||
| 123 | tmp = spi_sh_read(ss, offset); | ||
| 124 | tmp &= ~val; | ||
| 125 | spi_sh_write(ss, tmp, offset); | ||
| 126 | } | ||
| 127 | |||
| 128 | static void clear_fifo(struct spi_sh_data *ss) | ||
| 129 | { | ||
| 130 | spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); | ||
| 131 | spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); | ||
| 132 | } | ||
| 133 | |||
| 134 | static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss) | ||
| 135 | { | ||
| 136 | int timeout = 100000; | ||
| 137 | |||
| 138 | while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { | ||
| 139 | udelay(10); | ||
| 140 | if (timeout-- < 0) | ||
| 141 | return -ETIMEDOUT; | ||
| 142 | } | ||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss) | ||
| 147 | { | ||
| 148 | int timeout = 100000; | ||
| 149 | |||
| 150 | while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) { | ||
| 151 | udelay(10); | ||
| 152 | if (timeout-- < 0) | ||
| 153 | return -ETIMEDOUT; | ||
| 154 | } | ||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg, | ||
| 159 | struct spi_transfer *t) | ||
| 160 | { | ||
| 161 | int i, retval = 0; | ||
| 162 | int remain = t->len; | ||
| 163 | int cur_len; | ||
| 164 | unsigned char *data; | ||
| 165 | unsigned long tmp; | ||
| 166 | long ret; | ||
| 167 | |||
| 168 | if (t->len) | ||
| 169 | spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); | ||
| 170 | |||
| 171 | data = (unsigned char *)t->tx_buf; | ||
| 172 | while (remain > 0) { | ||
| 173 | cur_len = min(SPI_SH_FIFO_SIZE, remain); | ||
| 174 | for (i = 0; i < cur_len && | ||
| 175 | !(spi_sh_read(ss, SPI_SH_CR4) & | ||
| 176 | SPI_SH_WPABRT) && | ||
| 177 | !(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF); | ||
| 178 | i++) | ||
| 179 | spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR); | ||
| 180 | |||
| 181 | if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) { | ||
| 182 | /* Abort SPI operation */ | ||
| 183 | spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4); | ||
| 184 | retval = -EIO; | ||
| 185 | break; | ||
| 186 | } | ||
| 187 | |||
| 188 | cur_len = i; | ||
| 189 | |||
| 190 | remain -= cur_len; | ||
| 191 | data += cur_len; | ||
| 192 | |||
| 193 | if (remain > 0) { | ||
| 194 | ss->cr1 &= ~SPI_SH_TBE; | ||
| 195 | spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); | ||
| 196 | ret = wait_event_interruptible_timeout(ss->wait, | ||
| 197 | ss->cr1 & SPI_SH_TBE, | ||
| 198 | SPI_SH_SEND_TIMEOUT); | ||
| 199 | if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) { | ||
| 200 | printk(KERN_ERR "%s: timeout\n", __func__); | ||
| 201 | return -ETIMEDOUT; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | if (list_is_last(&t->transfer_list, &mesg->transfers)) { | ||
| 207 | tmp = spi_sh_read(ss, SPI_SH_CR1); | ||
| 208 | tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB); | ||
| 209 | spi_sh_write(ss, tmp, SPI_SH_CR1); | ||
| 210 | spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); | ||
| 211 | |||
| 212 | ss->cr1 &= ~SPI_SH_TBE; | ||
| 213 | spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); | ||
| 214 | ret = wait_event_interruptible_timeout(ss->wait, | ||
| 215 | ss->cr1 & SPI_SH_TBE, | ||
| 216 | SPI_SH_SEND_TIMEOUT); | ||
| 217 | if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) { | ||
| 218 | printk(KERN_ERR "%s: timeout\n", __func__); | ||
| 219 | return -ETIMEDOUT; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | return retval; | ||
| 224 | } | ||
| 225 | |||
| 226 | static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg, | ||
| 227 | struct spi_transfer *t) | ||
| 228 | { | ||
| 229 | int i; | ||
| 230 | int remain = t->len; | ||
| 231 | int cur_len; | ||
| 232 | unsigned char *data; | ||
| 233 | unsigned long tmp; | ||
| 234 | long ret; | ||
| 235 | |||
| 236 | if (t->len > SPI_SH_MAX_BYTE) | ||
| 237 | spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3); | ||
| 238 | else | ||
| 239 | spi_sh_write(ss, t->len, SPI_SH_CR3); | ||
| 240 | |||
| 241 | tmp = spi_sh_read(ss, SPI_SH_CR1); | ||
| 242 | tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB); | ||
| 243 | spi_sh_write(ss, tmp, SPI_SH_CR1); | ||
| 244 | spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); | ||
| 245 | |||
| 246 | spi_sh_wait_write_buffer_empty(ss); | ||
| 247 | |||
| 248 | data = (unsigned char *)t->rx_buf; | ||
| 249 | while (remain > 0) { | ||
| 250 | if (remain >= SPI_SH_FIFO_SIZE) { | ||
| 251 | ss->cr1 &= ~SPI_SH_RBF; | ||
| 252 | spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4); | ||
| 253 | ret = wait_event_interruptible_timeout(ss->wait, | ||
| 254 | ss->cr1 & SPI_SH_RBF, | ||
| 255 | SPI_SH_RECEIVE_TIMEOUT); | ||
| 256 | if (ret == 0 && | ||
| 257 | spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { | ||
| 258 | printk(KERN_ERR "%s: timeout\n", __func__); | ||
| 259 | return -ETIMEDOUT; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | cur_len = min(SPI_SH_FIFO_SIZE, remain); | ||
| 264 | for (i = 0; i < cur_len; i++) { | ||
| 265 | if (spi_sh_wait_receive_buffer(ss)) | ||
| 266 | break; | ||
| 267 | data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR); | ||
| 268 | } | ||
| 269 | |||
| 270 | remain -= cur_len; | ||
| 271 | data += cur_len; | ||
| 272 | } | ||
| 273 | |||
| 274 | /* deassert CS when SPI is receiving. */ | ||
| 275 | if (t->len > SPI_SH_MAX_BYTE) { | ||
| 276 | clear_fifo(ss); | ||
| 277 | spi_sh_write(ss, 1, SPI_SH_CR3); | ||
| 278 | } else { | ||
| 279 | spi_sh_write(ss, 0, SPI_SH_CR3); | ||
| 280 | } | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | static void spi_sh_work(struct work_struct *work) | ||
| 286 | { | ||
| 287 | struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws); | ||
| 288 | struct spi_message *mesg; | ||
| 289 | struct spi_transfer *t; | ||
| 290 | unsigned long flags; | ||
| 291 | int ret; | ||
| 292 | |||
| 293 | pr_debug("%s: enter\n", __func__); | ||
| 294 | |||
| 295 | spin_lock_irqsave(&ss->lock, flags); | ||
| 296 | while (!list_empty(&ss->queue)) { | ||
| 297 | mesg = list_entry(ss->queue.next, struct spi_message, queue); | ||
| 298 | list_del_init(&mesg->queue); | ||
| 299 | |||
| 300 | spin_unlock_irqrestore(&ss->lock, flags); | ||
| 301 | list_for_each_entry(t, &mesg->transfers, transfer_list) { | ||
| 302 | pr_debug("tx_buf = %p, rx_buf = %p\n", | ||
| 303 | t->tx_buf, t->rx_buf); | ||
| 304 | pr_debug("len = %d, delay_usecs = %d\n", | ||
| 305 | t->len, t->delay_usecs); | ||
| 306 | |||
| 307 | if (t->tx_buf) { | ||
| 308 | ret = spi_sh_send(ss, mesg, t); | ||
| 309 | if (ret < 0) | ||
| 310 | goto error; | ||
| 311 | } | ||
| 312 | if (t->rx_buf) { | ||
| 313 | ret = spi_sh_receive(ss, mesg, t); | ||
| 314 | if (ret < 0) | ||
| 315 | goto error; | ||
| 316 | } | ||
| 317 | mesg->actual_length += t->len; | ||
| 318 | } | ||
| 319 | spin_lock_irqsave(&ss->lock, flags); | ||
| 320 | |||
| 321 | mesg->status = 0; | ||
| 322 | mesg->complete(mesg->context); | ||
| 323 | } | ||
| 324 | |||
| 325 | clear_fifo(ss); | ||
| 326 | spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1); | ||
| 327 | udelay(100); | ||
| 328 | |||
| 329 | spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, | ||
| 330 | SPI_SH_CR1); | ||
| 331 | |||
| 332 | clear_fifo(ss); | ||
| 333 | |||
| 334 | spin_unlock_irqrestore(&ss->lock, flags); | ||
| 335 | |||
| 336 | return; | ||
| 337 | |||
| 338 | error: | ||
| 339 | mesg->status = ret; | ||
| 340 | mesg->complete(mesg->context); | ||
| 341 | |||
| 342 | spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, | ||
| 343 | SPI_SH_CR1); | ||
| 344 | clear_fifo(ss); | ||
| 345 | |||
| 346 | } | ||
| 347 | |||
| 348 | static int spi_sh_setup(struct spi_device *spi) | ||
| 349 | { | ||
| 350 | struct spi_sh_data *ss = spi_master_get_devdata(spi->master); | ||
| 351 | |||
| 352 | if (!spi->bits_per_word) | ||
| 353 | spi->bits_per_word = 8; | ||
| 354 | |||
| 355 | pr_debug("%s: enter\n", __func__); | ||
| 356 | |||
| 357 | spi_sh_write(ss, 0xfe, SPI_SH_CR1); /* SPI sycle stop */ | ||
| 358 | spi_sh_write(ss, 0x00, SPI_SH_CR1); /* CR1 init */ | ||
| 359 | spi_sh_write(ss, 0x00, SPI_SH_CR3); /* CR3 init */ | ||
| 360 | |||
| 361 | clear_fifo(ss); | ||
| 362 | |||
| 363 | /* 1/8 clock */ | ||
| 364 | spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2); | ||
| 365 | udelay(10); | ||
| 366 | |||
| 367 | return 0; | ||
| 368 | } | ||
| 369 | |||
| 370 | static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg) | ||
| 371 | { | ||
| 372 | struct spi_sh_data *ss = spi_master_get_devdata(spi->master); | ||
| 373 | unsigned long flags; | ||
| 374 | |||
| 375 | pr_debug("%s: enter\n", __func__); | ||
| 376 | pr_debug("\tmode = %02x\n", spi->mode); | ||
| 377 | |||
| 378 | spin_lock_irqsave(&ss->lock, flags); | ||
| 379 | |||
| 380 | mesg->actual_length = 0; | ||
| 381 | mesg->status = -EINPROGRESS; | ||
| 382 | |||
| 383 | spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1); | ||
| 384 | |||
| 385 | list_add_tail(&mesg->queue, &ss->queue); | ||
| 386 | queue_work(ss->workqueue, &ss->ws); | ||
| 387 | |||
| 388 | spin_unlock_irqrestore(&ss->lock, flags); | ||
| 389 | |||
| 390 | return 0; | ||
| 391 | } | ||
| 392 | |||
| 393 | static void spi_sh_cleanup(struct spi_device *spi) | ||
| 394 | { | ||
| 395 | struct spi_sh_data *ss = spi_master_get_devdata(spi->master); | ||
| 396 | |||
| 397 | pr_debug("%s: enter\n", __func__); | ||
| 398 | |||
| 399 | spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, | ||
| 400 | SPI_SH_CR1); | ||
| 401 | } | ||
| 402 | |||
| 403 | static irqreturn_t spi_sh_irq(int irq, void *_ss) | ||
| 404 | { | ||
| 405 | struct spi_sh_data *ss = (struct spi_sh_data *)_ss; | ||
| 406 | unsigned long cr1; | ||
| 407 | |||
| 408 | cr1 = spi_sh_read(ss, SPI_SH_CR1); | ||
| 409 | if (cr1 & SPI_SH_TBE) | ||
| 410 | ss->cr1 |= SPI_SH_TBE; | ||
| 411 | if (cr1 & SPI_SH_TBF) | ||
| 412 | ss->cr1 |= SPI_SH_TBF; | ||
| 413 | if (cr1 & SPI_SH_RBE) | ||
| 414 | ss->cr1 |= SPI_SH_RBE; | ||
| 415 | if (cr1 & SPI_SH_RBF) | ||
| 416 | ss->cr1 |= SPI_SH_RBF; | ||
| 417 | |||
| 418 | if (ss->cr1) { | ||
| 419 | spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4); | ||
| 420 | wake_up(&ss->wait); | ||
| 421 | } | ||
| 422 | |||
| 423 | return IRQ_HANDLED; | ||
| 424 | } | ||
| 425 | |||
| 426 | static int __devexit spi_sh_remove(struct platform_device *pdev) | ||
| 427 | { | ||
| 428 | struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev); | ||
| 429 | |||
| 430 | destroy_workqueue(ss->workqueue); | ||
| 431 | free_irq(ss->irq, ss); | ||
| 432 | iounmap(ss->addr); | ||
| 433 | spi_master_put(ss->master); | ||
| 434 | |||
| 435 | return 0; | ||
| 436 | } | ||
| 437 | |||
| 438 | static int __devinit spi_sh_probe(struct platform_device *pdev) | ||
| 439 | { | ||
| 440 | struct resource *res; | ||
| 441 | struct spi_master *master; | ||
| 442 | struct spi_sh_data *ss; | ||
| 443 | int ret, irq; | ||
| 444 | |||
| 445 | /* get base addr */ | ||
| 446 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 447 | if (unlikely(res == NULL)) { | ||
| 448 | dev_err(&pdev->dev, "invalid resource\n"); | ||
| 449 | return -EINVAL; | ||
| 450 | } | ||
| 451 | |||
| 452 | irq = platform_get_irq(pdev, 0); | ||
| 453 | if (irq < 0) { | ||
| 454 | dev_err(&pdev->dev, "platform_get_irq error\n"); | ||
| 455 | return -ENODEV; | ||
| 456 | } | ||
| 457 | |||
| 458 | master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); | ||
| 459 | if (master == NULL) { | ||
| 460 | dev_err(&pdev->dev, "spi_alloc_master error.\n"); | ||
| 461 | return -ENOMEM; | ||
| 462 | } | ||
| 463 | |||
| 464 | ss = spi_master_get_devdata(master); | ||
| 465 | dev_set_drvdata(&pdev->dev, ss); | ||
| 466 | |||
| 467 | ss->irq = irq; | ||
| 468 | ss->master = master; | ||
| 469 | ss->addr = ioremap(res->start, resource_size(res)); | ||
| 470 | if (ss->addr == NULL) { | ||
| 471 | dev_err(&pdev->dev, "ioremap error.\n"); | ||
| 472 | ret = -ENOMEM; | ||
| 473 | goto error1; | ||
| 474 | } | ||
| 475 | INIT_LIST_HEAD(&ss->queue); | ||
| 476 | spin_lock_init(&ss->lock); | ||
| 477 | INIT_WORK(&ss->ws, spi_sh_work); | ||
| 478 | init_waitqueue_head(&ss->wait); | ||
| 479 | ss->workqueue = create_singlethread_workqueue( | ||
| 480 | dev_name(master->dev.parent)); | ||
| 481 | if (ss->workqueue == NULL) { | ||
| 482 | dev_err(&pdev->dev, "create workqueue error\n"); | ||
| 483 | ret = -EBUSY; | ||
| 484 | goto error2; | ||
| 485 | } | ||
| 486 | |||
| 487 | ret = request_irq(irq, spi_sh_irq, IRQF_DISABLED, "spi_sh", ss); | ||
| 488 | if (ret < 0) { | ||
| 489 | dev_err(&pdev->dev, "request_irq error\n"); | ||
| 490 | goto error3; | ||
| 491 | } | ||
| 492 | |||
| 493 | master->num_chipselect = 2; | ||
| 494 | master->bus_num = pdev->id; | ||
| 495 | master->setup = spi_sh_setup; | ||
| 496 | master->transfer = spi_sh_transfer; | ||
| 497 | master->cleanup = spi_sh_cleanup; | ||
| 498 | |||
| 499 | ret = spi_register_master(master); | ||
| 500 | if (ret < 0) { | ||
| 501 | printk(KERN_ERR "spi_register_master error.\n"); | ||
| 502 | goto error4; | ||
| 503 | } | ||
| 504 | |||
| 505 | return 0; | ||
| 506 | |||
| 507 | error4: | ||
| 508 | free_irq(irq, ss); | ||
| 509 | error3: | ||
| 510 | destroy_workqueue(ss->workqueue); | ||
| 511 | error2: | ||
| 512 | iounmap(ss->addr); | ||
| 513 | error1: | ||
| 514 | spi_master_put(master); | ||
| 515 | |||
| 516 | return ret; | ||
| 517 | } | ||
| 518 | |||
| 519 | static struct platform_driver spi_sh_driver = { | ||
| 520 | .probe = spi_sh_probe, | ||
| 521 | .remove = __devexit_p(spi_sh_remove), | ||
| 522 | .driver = { | ||
| 523 | .name = "sh_spi", | ||
| 524 | .owner = THIS_MODULE, | ||
| 525 | }, | ||
| 526 | }; | ||
| 527 | |||
| 528 | static int __init spi_sh_init(void) | ||
| 529 | { | ||
| 530 | return platform_driver_register(&spi_sh_driver); | ||
| 531 | } | ||
| 532 | module_init(spi_sh_init); | ||
| 533 | |||
| 534 | static void __exit spi_sh_exit(void) | ||
| 535 | { | ||
| 536 | platform_driver_unregister(&spi_sh_driver); | ||
| 537 | } | ||
| 538 | module_exit(spi_sh_exit); | ||
| 539 | |||
| 540 | MODULE_DESCRIPTION("SH SPI bus driver"); | ||
| 541 | MODULE_LICENSE("GPL"); | ||
| 542 | MODULE_AUTHOR("Yoshihiro Shimoda"); | ||
| 543 | MODULE_ALIAS("platform:sh_spi"); | ||
diff --git a/drivers/spi/spi_sh_msiof.c b/drivers/spi/spi_sh_msiof.c index 2c665fceaac7..e00d94b22250 100644 --- a/drivers/spi/spi_sh_msiof.c +++ b/drivers/spi/spi_sh_msiof.c | |||
| @@ -9,22 +9,22 @@ | |||
| 9 | * | 9 | * |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/bitmap.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/clk.h> |
| 14 | #include <linux/completion.h> | ||
| 14 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/gpio.h> | ||
| 18 | #include <linux/init.h> | ||
| 15 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 20 | #include <linux/io.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 16 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
| 17 | #include <linux/completion.h> | ||
| 18 | #include <linux/pm_runtime.h> | 23 | #include <linux/pm_runtime.h> |
| 19 | #include <linux/gpio.h> | ||
| 20 | #include <linux/bitmap.h> | ||
| 21 | #include <linux/clk.h> | ||
| 22 | #include <linux/io.h> | ||
| 23 | #include <linux/err.h> | ||
| 24 | 24 | ||
| 25 | #include <linux/spi/sh_msiof.h> | ||
| 25 | #include <linux/spi/spi.h> | 26 | #include <linux/spi/spi.h> |
| 26 | #include <linux/spi/spi_bitbang.h> | 27 | #include <linux/spi/spi_bitbang.h> |
| 27 | #include <linux/spi/sh_msiof.h> | ||
| 28 | 28 | ||
| 29 | #include <asm/unaligned.h> | 29 | #include <asm/unaligned.h> |
| 30 | 30 | ||
| @@ -67,7 +67,7 @@ struct sh_msiof_spi_priv { | |||
| 67 | #define STR_TEOF (1 << 23) | 67 | #define STR_TEOF (1 << 23) |
| 68 | #define STR_REOF (1 << 7) | 68 | #define STR_REOF (1 << 7) |
| 69 | 69 | ||
| 70 | static unsigned long sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) | 70 | static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) |
| 71 | { | 71 | { |
| 72 | switch (reg_offs) { | 72 | switch (reg_offs) { |
| 73 | case TSCR: | 73 | case TSCR: |
| @@ -79,7 +79,7 @@ static unsigned long sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) | |||
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs, | 81 | static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs, |
| 82 | unsigned long value) | 82 | u32 value) |
| 83 | { | 83 | { |
| 84 | switch (reg_offs) { | 84 | switch (reg_offs) { |
| 85 | case TSCR: | 85 | case TSCR: |
| @@ -93,10 +93,10 @@ static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs, | |||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p, | 95 | static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p, |
| 96 | unsigned long clr, unsigned long set) | 96 | u32 clr, u32 set) |
| 97 | { | 97 | { |
| 98 | unsigned long mask = clr | set; | 98 | u32 mask = clr | set; |
| 99 | unsigned long data; | 99 | u32 data; |
| 100 | int k; | 100 | int k; |
| 101 | 101 | ||
| 102 | data = sh_msiof_read(p, CTR); | 102 | data = sh_msiof_read(p, CTR); |
| @@ -166,10 +166,10 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, | |||
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, | 168 | static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, |
| 169 | int cpol, int cpha, | 169 | u32 cpol, u32 cpha, |
| 170 | int tx_hi_z, int lsb_first) | 170 | u32 tx_hi_z, u32 lsb_first) |
| 171 | { | 171 | { |
| 172 | unsigned long tmp; | 172 | u32 tmp; |
| 173 | int edge; | 173 | int edge; |
| 174 | 174 | ||
| 175 | /* | 175 | /* |
| @@ -187,7 +187,7 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, | |||
| 187 | tmp |= cpol << 30; /* TSCKIZ */ | 187 | tmp |= cpol << 30; /* TSCKIZ */ |
| 188 | tmp |= cpol << 28; /* RSCKIZ */ | 188 | tmp |= cpol << 28; /* RSCKIZ */ |
| 189 | 189 | ||
| 190 | edge = cpol ? cpha : !cpha; | 190 | edge = cpol ^ !cpha; |
| 191 | 191 | ||
| 192 | tmp |= edge << 27; /* TEDG */ | 192 | tmp |= edge << 27; /* TEDG */ |
| 193 | tmp |= edge << 26; /* REDG */ | 193 | tmp |= edge << 26; /* REDG */ |
| @@ -197,11 +197,9 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, | |||
| 197 | 197 | ||
| 198 | static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p, | 198 | static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p, |
| 199 | const void *tx_buf, void *rx_buf, | 199 | const void *tx_buf, void *rx_buf, |
| 200 | int bits, int words) | 200 | u32 bits, u32 words) |
| 201 | { | 201 | { |
| 202 | unsigned long dr2; | 202 | u32 dr2 = ((bits - 1) << 24) | ((words - 1) << 16); |
| 203 | |||
| 204 | dr2 = ((bits - 1) << 24) | ((words - 1) << 16); | ||
| 205 | 203 | ||
| 206 | if (tx_buf) | 204 | if (tx_buf) |
| 207 | sh_msiof_write(p, TMDR2, dr2); | 205 | sh_msiof_write(p, TMDR2, dr2); |
| @@ -222,7 +220,7 @@ static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p) | |||
| 222 | static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p, | 220 | static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p, |
| 223 | const void *tx_buf, int words, int fs) | 221 | const void *tx_buf, int words, int fs) |
| 224 | { | 222 | { |
| 225 | const unsigned char *buf_8 = tx_buf; | 223 | const u8 *buf_8 = tx_buf; |
| 226 | int k; | 224 | int k; |
| 227 | 225 | ||
| 228 | for (k = 0; k < words; k++) | 226 | for (k = 0; k < words; k++) |
| @@ -232,7 +230,7 @@ static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p, | |||
| 232 | static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p, | 230 | static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p, |
| 233 | const void *tx_buf, int words, int fs) | 231 | const void *tx_buf, int words, int fs) |
| 234 | { | 232 | { |
| 235 | const unsigned short *buf_16 = tx_buf; | 233 | const u16 *buf_16 = tx_buf; |
| 236 | int k; | 234 | int k; |
| 237 | 235 | ||
| 238 | for (k = 0; k < words; k++) | 236 | for (k = 0; k < words; k++) |
| @@ -242,7 +240,7 @@ static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p, | |||
| 242 | static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p, | 240 | static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p, |
| 243 | const void *tx_buf, int words, int fs) | 241 | const void *tx_buf, int words, int fs) |
| 244 | { | 242 | { |
| 245 | const unsigned short *buf_16 = tx_buf; | 243 | const u16 *buf_16 = tx_buf; |
| 246 | int k; | 244 | int k; |
| 247 | 245 | ||
| 248 | for (k = 0; k < words; k++) | 246 | for (k = 0; k < words; k++) |
| @@ -252,7 +250,7 @@ static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p, | |||
| 252 | static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p, | 250 | static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p, |
| 253 | const void *tx_buf, int words, int fs) | 251 | const void *tx_buf, int words, int fs) |
| 254 | { | 252 | { |
| 255 | const unsigned int *buf_32 = tx_buf; | 253 | const u32 *buf_32 = tx_buf; |
| 256 | int k; | 254 | int k; |
| 257 | 255 | ||
| 258 | for (k = 0; k < words; k++) | 256 | for (k = 0; k < words; k++) |
| @@ -262,17 +260,37 @@ static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p, | |||
| 262 | static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p, | 260 | static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p, |
| 263 | const void *tx_buf, int words, int fs) | 261 | const void *tx_buf, int words, int fs) |
| 264 | { | 262 | { |
| 265 | const unsigned int *buf_32 = tx_buf; | 263 | const u32 *buf_32 = tx_buf; |
| 266 | int k; | 264 | int k; |
| 267 | 265 | ||
| 268 | for (k = 0; k < words; k++) | 266 | for (k = 0; k < words; k++) |
| 269 | sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs); | 267 | sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs); |
| 270 | } | 268 | } |
| 271 | 269 | ||
| 270 | static void sh_msiof_spi_write_fifo_s32(struct sh_msiof_spi_priv *p, | ||
| 271 | const void *tx_buf, int words, int fs) | ||
| 272 | { | ||
| 273 | const u32 *buf_32 = tx_buf; | ||
| 274 | int k; | ||
| 275 | |||
| 276 | for (k = 0; k < words; k++) | ||
| 277 | sh_msiof_write(p, TFDR, swab32(buf_32[k] << fs)); | ||
| 278 | } | ||
| 279 | |||
| 280 | static void sh_msiof_spi_write_fifo_s32u(struct sh_msiof_spi_priv *p, | ||
| 281 | const void *tx_buf, int words, int fs) | ||
| 282 | { | ||
| 283 | const u32 *buf_32 = tx_buf; | ||
| 284 | int k; | ||
| 285 | |||
| 286 | for (k = 0; k < words; k++) | ||
| 287 | sh_msiof_write(p, TFDR, swab32(get_unaligned(&buf_32[k]) << fs)); | ||
| 288 | } | ||
| 289 | |||
| 272 | static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p, | 290 | static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p, |
| 273 | void *rx_buf, int words, int fs) | 291 | void *rx_buf, int words, int fs) |
| 274 | { | 292 | { |
| 275 | unsigned char *buf_8 = rx_buf; | 293 | u8 *buf_8 = rx_buf; |
| 276 | int k; | 294 | int k; |
| 277 | 295 | ||
| 278 | for (k = 0; k < words; k++) | 296 | for (k = 0; k < words; k++) |
| @@ -282,7 +300,7 @@ static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p, | |||
| 282 | static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p, | 300 | static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p, |
| 283 | void *rx_buf, int words, int fs) | 301 | void *rx_buf, int words, int fs) |
| 284 | { | 302 | { |
| 285 | unsigned short *buf_16 = rx_buf; | 303 | u16 *buf_16 = rx_buf; |
| 286 | int k; | 304 | int k; |
| 287 | 305 | ||
| 288 | for (k = 0; k < words; k++) | 306 | for (k = 0; k < words; k++) |
| @@ -292,7 +310,7 @@ static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p, | |||
| 292 | static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p, | 310 | static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p, |
| 293 | void *rx_buf, int words, int fs) | 311 | void *rx_buf, int words, int fs) |
| 294 | { | 312 | { |
| 295 | unsigned short *buf_16 = rx_buf; | 313 | u16 *buf_16 = rx_buf; |
| 296 | int k; | 314 | int k; |
| 297 | 315 | ||
| 298 | for (k = 0; k < words; k++) | 316 | for (k = 0; k < words; k++) |
| @@ -302,7 +320,7 @@ static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p, | |||
| 302 | static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p, | 320 | static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p, |
| 303 | void *rx_buf, int words, int fs) | 321 | void *rx_buf, int words, int fs) |
| 304 | { | 322 | { |
| 305 | unsigned int *buf_32 = rx_buf; | 323 | u32 *buf_32 = rx_buf; |
| 306 | int k; | 324 | int k; |
| 307 | 325 | ||
| 308 | for (k = 0; k < words; k++) | 326 | for (k = 0; k < words; k++) |
| @@ -312,19 +330,40 @@ static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p, | |||
| 312 | static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p, | 330 | static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p, |
| 313 | void *rx_buf, int words, int fs) | 331 | void *rx_buf, int words, int fs) |
| 314 | { | 332 | { |
| 315 | unsigned int *buf_32 = rx_buf; | 333 | u32 *buf_32 = rx_buf; |
| 316 | int k; | 334 | int k; |
| 317 | 335 | ||
| 318 | for (k = 0; k < words; k++) | 336 | for (k = 0; k < words; k++) |
| 319 | put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]); | 337 | put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]); |
| 320 | } | 338 | } |
| 321 | 339 | ||
| 340 | static void sh_msiof_spi_read_fifo_s32(struct sh_msiof_spi_priv *p, | ||
| 341 | void *rx_buf, int words, int fs) | ||
| 342 | { | ||
| 343 | u32 *buf_32 = rx_buf; | ||
| 344 | int k; | ||
| 345 | |||
| 346 | for (k = 0; k < words; k++) | ||
| 347 | buf_32[k] = swab32(sh_msiof_read(p, RFDR) >> fs); | ||
| 348 | } | ||
| 349 | |||
| 350 | static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p, | ||
| 351 | void *rx_buf, int words, int fs) | ||
| 352 | { | ||
| 353 | u32 *buf_32 = rx_buf; | ||
| 354 | int k; | ||
| 355 | |||
| 356 | for (k = 0; k < words; k++) | ||
| 357 | put_unaligned(swab32(sh_msiof_read(p, RFDR) >> fs), &buf_32[k]); | ||
| 358 | } | ||
| 359 | |||
| 322 | static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t) | 360 | static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t) |
| 323 | { | 361 | { |
| 324 | int bits; | 362 | int bits; |
| 325 | 363 | ||
| 326 | bits = t ? t->bits_per_word : 0; | 364 | bits = t ? t->bits_per_word : 0; |
| 327 | bits = bits ? bits : spi->bits_per_word; | 365 | if (!bits) |
| 366 | bits = spi->bits_per_word; | ||
| 328 | return bits; | 367 | return bits; |
| 329 | } | 368 | } |
| 330 | 369 | ||
| @@ -334,7 +373,8 @@ static unsigned long sh_msiof_spi_hz(struct spi_device *spi, | |||
| 334 | unsigned long hz; | 373 | unsigned long hz; |
| 335 | 374 | ||
| 336 | hz = t ? t->speed_hz : 0; | 375 | hz = t ? t->speed_hz : 0; |
| 337 | hz = hz ? hz : spi->max_speed_hz; | 376 | if (!hz) |
| 377 | hz = spi->max_speed_hz; | ||
| 338 | return hz; | 378 | return hz; |
| 339 | } | 379 | } |
| 340 | 380 | ||
| @@ -468,9 +508,17 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t) | |||
| 468 | int bytes_done; | 508 | int bytes_done; |
| 469 | int words; | 509 | int words; |
| 470 | int n; | 510 | int n; |
| 511 | bool swab; | ||
| 471 | 512 | ||
| 472 | bits = sh_msiof_spi_bits(spi, t); | 513 | bits = sh_msiof_spi_bits(spi, t); |
| 473 | 514 | ||
| 515 | if (bits <= 8 && t->len > 15 && !(t->len & 3)) { | ||
| 516 | bits = 32; | ||
| 517 | swab = true; | ||
| 518 | } else { | ||
| 519 | swab = false; | ||
| 520 | } | ||
| 521 | |||
| 474 | /* setup bytes per word and fifo read/write functions */ | 522 | /* setup bytes per word and fifo read/write functions */ |
| 475 | if (bits <= 8) { | 523 | if (bits <= 8) { |
| 476 | bytes_per_word = 1; | 524 | bytes_per_word = 1; |
| @@ -487,6 +535,17 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t) | |||
| 487 | rx_fifo = sh_msiof_spi_read_fifo_16u; | 535 | rx_fifo = sh_msiof_spi_read_fifo_16u; |
| 488 | else | 536 | else |
| 489 | rx_fifo = sh_msiof_spi_read_fifo_16; | 537 | rx_fifo = sh_msiof_spi_read_fifo_16; |
| 538 | } else if (swab) { | ||
| 539 | bytes_per_word = 4; | ||
| 540 | if ((unsigned long)t->tx_buf & 0x03) | ||
| 541 | tx_fifo = sh_msiof_spi_write_fifo_s32u; | ||
| 542 | else | ||
| 543 | tx_fifo = sh_msiof_spi_write_fifo_s32; | ||
| 544 | |||
| 545 | if ((unsigned long)t->rx_buf & 0x03) | ||
| 546 | rx_fifo = sh_msiof_spi_read_fifo_s32u; | ||
| 547 | else | ||
| 548 | rx_fifo = sh_msiof_spi_read_fifo_s32; | ||
| 490 | } else { | 549 | } else { |
| 491 | bytes_per_word = 4; | 550 | bytes_per_word = 4; |
| 492 | if ((unsigned long)t->tx_buf & 0x03) | 551 | if ((unsigned long)t->tx_buf & 0x03) |
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 603428213d21..d9fd86211365 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/errno.h> | 30 | #include <linux/errno.h> |
| 31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/compat.h> | ||
| 33 | 34 | ||
| 34 | #include <linux/spi/spi.h> | 35 | #include <linux/spi/spi.h> |
| 35 | #include <linux/spi/spidev.h> | 36 | #include <linux/spi/spidev.h> |
| @@ -471,6 +472,16 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 471 | return retval; | 472 | return retval; |
| 472 | } | 473 | } |
| 473 | 474 | ||
| 475 | #ifdef CONFIG_COMPAT | ||
| 476 | static long | ||
| 477 | spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
| 478 | { | ||
| 479 | return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); | ||
| 480 | } | ||
| 481 | #else | ||
| 482 | #define spidev_compat_ioctl NULL | ||
| 483 | #endif /* CONFIG_COMPAT */ | ||
| 484 | |||
| 474 | static int spidev_open(struct inode *inode, struct file *filp) | 485 | static int spidev_open(struct inode *inode, struct file *filp) |
| 475 | { | 486 | { |
| 476 | struct spidev_data *spidev; | 487 | struct spidev_data *spidev; |
| @@ -543,6 +554,7 @@ static const struct file_operations spidev_fops = { | |||
| 543 | .write = spidev_write, | 554 | .write = spidev_write, |
| 544 | .read = spidev_read, | 555 | .read = spidev_read, |
| 545 | .unlocked_ioctl = spidev_ioctl, | 556 | .unlocked_ioctl = spidev_ioctl, |
| 557 | .compat_ioctl = spidev_compat_ioctl, | ||
| 546 | .open = spidev_open, | 558 | .open = spidev_open, |
| 547 | .release = spidev_release, | 559 | .release = spidev_release, |
| 548 | .llseek = no_llseek, | 560 | .llseek = no_llseek, |
diff --git a/include/linux/spi/mcp23s08.h b/include/linux/spi/mcp23s08.h index 22ef107d7704..c42cff8ca191 100644 --- a/include/linux/spi/mcp23s08.h +++ b/include/linux/spi/mcp23s08.h | |||
| @@ -2,21 +2,24 @@ | |||
| 2 | /* FIXME driver should be able to handle IRQs... */ | 2 | /* FIXME driver should be able to handle IRQs... */ |
| 3 | 3 | ||
| 4 | struct mcp23s08_chip_info { | 4 | struct mcp23s08_chip_info { |
| 5 | bool is_present; /* true iff populated */ | 5 | bool is_present; /* true if populated */ |
| 6 | u8 pullups; /* BIT(x) means enable pullup x */ | 6 | unsigned pullups; /* BIT(x) means enable pullup x */ |
| 7 | }; | 7 | }; |
| 8 | 8 | ||
| 9 | struct mcp23s08_platform_data { | 9 | struct mcp23s08_platform_data { |
| 10 | /* Four slaves (numbered 0..3) can share one SPI chipselect, and | 10 | /* For mcp23s08, up to 4 slaves (numbered 0..3) can share one SPI |
| 11 | * will provide 8..32 GPIOs using 1..4 gpio_chip instances. | 11 | * chipselect, each providing 1 gpio_chip instance with 8 gpios. |
| 12 | * For mpc23s17, up to 8 slaves (numbered 0..7) can share one SPI | ||
| 13 | * chipselect, each providing 1 gpio_chip (port A + port B) with | ||
| 14 | * 16 gpios. | ||
| 12 | */ | 15 | */ |
| 13 | struct mcp23s08_chip_info chip[4]; | 16 | struct mcp23s08_chip_info chip[8]; |
| 14 | 17 | ||
| 15 | /* "base" is the number of the first GPIO. Dynamic assignment is | 18 | /* "base" is the number of the first GPIO. Dynamic assignment is |
| 16 | * not currently supported, and even if there are gaps in chip | 19 | * not currently supported, and even if there are gaps in chip |
| 17 | * addressing the GPIO numbers are sequential .. so for example | 20 | * addressing the GPIO numbers are sequential .. so for example |
| 18 | * if only slaves 0 and 3 are present, their GPIOs range from | 21 | * if only slaves 0 and 3 are present, their GPIOs range from |
| 19 | * base to base+15. | 22 | * base to base+15 (or base+31 for s17 variant). |
| 20 | */ | 23 | */ |
| 21 | unsigned base; | 24 | unsigned base; |
| 22 | 25 | ||
diff --git a/include/linux/spi/spi_oc_tiny.h b/include/linux/spi/spi_oc_tiny.h new file mode 100644 index 000000000000..1ac529cf4f06 --- /dev/null +++ b/include/linux/spi/spi_oc_tiny.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #ifndef _LINUX_SPI_SPI_OC_TINY_H | ||
| 2 | #define _LINUX_SPI_SPI_OC_TINY_H | ||
| 3 | |||
| 4 | /** | ||
| 5 | * struct tiny_spi_platform_data - platform data of the OpenCores tiny SPI | ||
| 6 | * @freq: input clock freq to the core. | ||
| 7 | * @baudwidth: baud rate divider width of the core. | ||
| 8 | * @gpio_cs_count: number of gpio pins used for chipselect. | ||
| 9 | * @gpio_cs: array of gpio pins used for chipselect. | ||
| 10 | * | ||
| 11 | * freq and baudwidth are used only if the divider is programmable. | ||
| 12 | */ | ||
| 13 | struct tiny_spi_platform_data { | ||
| 14 | unsigned int freq; | ||
| 15 | unsigned int baudwidth; | ||
| 16 | unsigned int gpio_cs_count; | ||
| 17 | int *gpio_cs; | ||
| 18 | }; | ||
| 19 | |||
| 20 | #endif /* _LINUX_SPI_SPI_OC_TINY_H */ | ||
