Commit Graph

16 Commits

Author SHA1 Message Date
David Brownell d1e44d9ce8 SPI driver runtime footprint shrinkage
Shrink the runtime footprint of various SPI drivers:

  - Move the probe() routine into the init section where practical,
    using platform_driver_probe() to make that safe.  This often saves
    around 1KB.  Using platform_driver_probe() can also be a correctness
    fix, if the probe routine is already marked __init but the driver
    struct keeps a dangling pointer to it after init section removal.

  - Likewise move remove() routines into the exit sections.

These changes would be inappropriate iff the platform devices were
actually hotpluggable (e.g. they're found on optional addon cards,
or in an FPGA that's dynamically reprogrammed).  In these cases,
that's not the situation; it's an SOC controller and the only device
is initialized before these drivers.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-16 09:43:09 -07:00
Jan Andersson 65e213cdb2 spi_mpc83xx: hang fix
When the spi_mpc83xx driver receives a tx_buf pointer which is NULL, it
only writes one zero filled word to the transmit register.  If the driver
expects to receive more than one word it will wait forever for a second
receive interrupt.  With this patch the controller will shift out zeroes
until all words have been received.

Signed-off-by: Jan Andersson <jan@gaisler.com>
Tested-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Acked-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-09-11 17:21:19 -07:00
David Brownell fc3ba9525b SPI driver hotplug/coldplug fixes
Update various SPI drivers so they properly support

  - coldplug through "modprobe $(cat /sys/devices/.../modalias)"

  - hotplug through "modprobe $(MODALIAS)"

The basic rule for platform, SPI, and (new style) I2C drivers is just
to make sure that modprobing the driver name works.  In this case, all
the relevant drivers are platform drivers, and this patch either

  (a)	Changes the driver name, if no in-tree code would break;
	this is simpler and thus preferable in the long term.

  (b)	Adds MODULE_ALIAS directives, when in-tree platforms declare
	devices using the current driver name; less desirable.

Most systems will link SPI controller drivers statically, but
there's no point in being needlessly broken.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Jean Delvare <khali@linux-fr.org>
Acked-by: Andrei Konovalov <akonovalov@ru.mvista.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-08-31 01:42:22 -07:00
Anton Vorontsov a44648b057 spi_mpc83xx: fix prescale modulus calculation
Long ago I've noticed (but didn't pay much attention) that
spi_mpc83xx using PM calculations that differs from what
specs describe. I.e.

u8 pm = mpc83xx_spi->spibrg / (spi->max_speed_hz * 4);

While specs says: "The SPI baud rate generator clock source (either
system clock or system clock divided by 16, depending on DIV16 bit) is
divided by 4 * ([PM] + 1), a range from 4 to 64.".

Thus " - 1" is missing in the spi_mpc83xx's formula.

Why nobody noticed that bug? Probably because sysclk usually less then
user expects, e.g. you expect 200 MHz, but real clock is 198 MHz,
and integer rounding helps when this formula is used.

Suppose it's SPI in QE, SYSCLK at 198 MHz, thus SPIBRG at 99MHz, 25 MHz
requested.

PM = (99MHz / ( 25 MHz * 4 )), PM == 0, output SPICLK will be 24.75 MHz

At lower frequencies this bug is more noticeable, though.

And this bug shows itself in all its beauty if SYSCLK is equal or a bit
more than you expect (200 MHz SYSCLK, 100 MHz SPIBRG):
PM = (100MHz / ( 25 MHz * 4 )), PM == 1, output SPICLK will be 12.625 MHz!

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-08-11 15:47:41 -07:00
Anton Vorontsov e24a4d1ee3 spi_mpc83xx: in "QE mode", use sysclk/2
For MPC8349E input to the SPI Baud Rate Generator is SYSCLK, but it's
SYSCLK/2 for MPC8323E (SPI in QE).  Fix this, and remove confusion by
renaming the mpc83xx_spi->sysclk member as mpc83xx_spi->spibrg.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-08-11 15:47:41 -07:00
Anton Vorontsov 2a485d7ad2 spi_mpc83xx: support loopback mode
This exposes the hardware loopback mode to drivers, primarily for testing.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-31 15:39:40 -07:00
Anton Vorontsov 35cc0b9750 spi_mpc83xx: fix QE+LSB mode shifts
spi_mpc83xx should use other shifts when running in QE+LSB mode.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-31 15:39:40 -07:00
Anton Vorontsov 32421daaf8 spi_mpc83xx: support for lsb-first transfers
This controller supports LSB-first transfers; let drivers use them.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-31 15:39:39 -07:00
Anton Vorontsov 20ba09b979 spi_mpc83xx: get rid of magic numbers
Magic-numbers-R-Evil

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-31 15:39:39 -07:00
Anton Vorontsov 49bb23006b spi_mpc83xx: turn off SPI unit while switching mode
Documentation clearly states, that mode should not be changed till
SPMODE_ENABLE bit set.  I've seen hangs w/o this patch.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-31 15:39:39 -07:00
Joakim Tjernlund f29ba280ec spi_mpc83xx.c: support QE enabled 83xx CPU's like mpc832x
Quicc Engine enabled mpc83xx CPU's has a somewhat different HW interface to
the SPI controller.  This patch adds a qe_mode knob that sees to that
needed adaptions are performed.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-17 10:23:05 -07:00
Clifford Wolf 698ca47e8d spi_mpc83xx.c underclocking hotfix
The MPC83xx SPI controller clock divider can divide the system clock by not
more then 1024.  The spi_mpc83xx driver does not check this and silently
writes garbage to the SPI controller registers when asked to run at lower
frequencies.  I've tried to run the SPI on a 266MHz MPC8349E with 100kHz
for debugging a bus problem and suddenly was confronted with a 2nd problem
to debug..  ;-)

The patch adds an additional check which avoids writing garbage to the SPI
controller registers and warn the user about it.  This might help others to
avoid simmilar problems.

Cc: Kumar Gala <galak@gate.crashing.org>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-17 10:23:04 -07:00
David Brownell dccd573bb0 SPI controller drivers: check for unsupported modes
Minor SPI controller driver updates: make the setup() methods reject
spi->mode bits they don't support, by masking aginst the inverse of bits
they *do* support.  This insures against misbehavior later when new mode
bits get added.

Most controllers can't support SPI_LSB_FIRST; more handle SPI_CS_HIGH.
Support for all four SPI clock/transfer modes is routine.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-17 10:23:04 -07:00
David Brownell 4b1badf5d9 [PATCH] SPI: define null tx_buf to mean "shift out zeroes"
Some issues were recently turned up with the current specification of what
it means for spi_transfer.tx_buf to be null, as part of transfers which are
(from the SPI protocol driver perspective) pure reads.

Specifically, that it seems better to change the TX behaviour there from
"undefined" to "will shift zeroes".  This lets protocol drivers (like the
ads7846 driver) depend on that behavior.  It's what most controller drivers
in the tree are already doing (with one exception and one case of driver
wanting-to-oops), it's what Microwire hardware will necessarily be doing,
and it removes an issue whereby certain security audits would need to
define such a value anyway as part of removing covert channels.

This patch changes the specification to require shifting zeroes, and
updates all currently merged SPI controller drivers to do so.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-30 10:56:42 -08:00
David Howells 7d12e780e0 IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.

The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around.  On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).

Where appropriate, an arch may override the generic storage facility and do
something different with the variable.  On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.

Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions.  Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller.  A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.

I've build this code with allyesconfig for x86_64 and i386.  I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.

This will affect all archs.  Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:

	struct pt_regs *old_regs = set_irq_regs(regs);

And put the old one back at the end:

	set_irq_regs(old_regs);

Don't pass regs through to generic_handle_irq() or __do_IRQ().

In timer_interrupt(), this sort of change will be necessary:

	-	update_process_times(user_mode(regs));
	-	profile_tick(CPU_PROFILING, regs);
	+	update_process_times(user_mode(get_irq_regs()));
	+	profile_tick(CPU_PROFILING);

I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().

Some notes on the interrupt handling in the drivers:

 (*) input_dev() is now gone entirely.  The regs pointer is no longer stored in
     the input_dev struct.

 (*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking.  It does
     something different depending on whether it's been supplied with a regs
     pointer or not.

 (*) Various IRQ handler function pointers have been moved to type
     irq_handler_t.

Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 15:10:12 +01:00
Kumar Gala ccf06998fe [PATCH] spi: add spi master driver for Freescale MPC83xx SPI controller
This driver supports the SPI controller on the MPC83xx SoC devices from
Freescale.  Note, this driver supports only the simple shift register SPI
controller and not the descriptor based CPM or QUICCEngine SPI controller.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-05-21 12:59:19 -07:00