Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
このコミットが含まれているのは:
Linus Torvalds
2005-04-16 15:20:36 -07:00
コミット 1da177e4c3
17291個のファイルの変更6718755行の追加0行の削除

663
drivers/mtd/maps/Kconfig ノーマルファイル
ファイルの表示

@@ -0,0 +1,663 @@
# drivers/mtd/maps/Kconfig
# $Id: Kconfig,v 1.42 2005/01/05 16:59:50 dwmw2 Exp $
menu "Mapping drivers for chip access"
depends on MTD!=n
config MTD_COMPLEX_MAPPINGS
bool "Support non-linear mappings of flash chips"
depends on MTD
help
This causes the chip drivers to allow for complicated
paged mappings of flash chips.
config MTD_PHYSMAP
tristate "CFI Flash device in physical memory map"
depends on MTD_CFI
help
This provides a 'mapping' driver which allows the CFI probe and
command set driver code to communicate with flash chips which
are mapped physically into the CPU's memory. You will need to
configure the physical address and size of the flash chips on
your particular board as well as the bus width, either statically
with config options or at run-time.
config MTD_PHYSMAP_START
hex "Physical start address of flash mapping"
depends on MTD_PHYSMAP
default "0x8000000"
help
This is the physical memory location at which the flash chips
are mapped on your particular target board. Refer to the
memory map which should hopefully be in the documentation for
your board.
Ignore this option if you use run-time physmap configuration
(i.e., run-time calling physmap_configure()).
config MTD_PHYSMAP_LEN
hex "Physical length of flash mapping"
depends on MTD_PHYSMAP
default "0x4000000"
help
This is the total length of the mapping of the flash chips on
your particular board. If there is space, or aliases, in the
physical memory map between the chips, this could be larger
than the total amount of flash present. Refer to the memory
map which should hopefully be in the documentation for your
board.
Ignore this option if you use run-time physmap configuration
(i.e., run-time calling physmap_configure()).
config MTD_PHYSMAP_BANKWIDTH
int "Bank width in octets"
depends on MTD_PHYSMAP
default "2"
help
This is the total width of the data bus of the flash devices
in octets. For example, if you have a data bus width of 32
bits, you would set the bus width octect value to 4. This is
used internally by the CFI drivers.
Ignore this option if you use run-time physmap configuration
(i.e., run-time calling physmap_configure()).
config MTD_SUN_UFLASH
tristate "Sun Microsystems userflash support"
depends on (SPARC32 || SPARC64) && MTD_CFI
help
This provides a 'mapping' driver which supports the way in
which user-programmable flash chips are connected on various
Sun Microsystems boardsets. This driver will require CFI support
in the kernel, so if you did not enable CFI previously, do that now.
config MTD_PNC2000
tristate "CFI Flash device mapped on Photron PNC-2000"
depends on X86 && MTD_CFI && MTD_PARTITIONS
help
PNC-2000 is the name of Network Camera product from PHOTRON
Ltd. in Japan. It uses CFI-compliant flash.
config MTD_SC520CDP
tristate "CFI Flash device mapped on AMD SC520 CDP"
depends on X86 && MTD_CFI
help
The SC520 CDP board has two banks of CFI-compliant chips and one
Dual-in-line JEDEC chip. This 'mapping' driver supports that
arrangement, implementing three MTD devices.
config MTD_NETSC520
tristate "CFI Flash device mapped on AMD NetSc520"
depends on X86 && MTD_CFI && MTD_PARTITIONS
help
This enables access routines for the flash chips on the AMD NetSc520
demonstration board. If you have one of these boards and would like
to use the flash chips on it, say 'Y'.
config MTD_TS5500
tristate "JEDEC Flash device mapped on Technologic Systems TS-5500"
depends on X86 && MTD_JEDECPROBE && MTD_PARTITIONS
help
This provides a driver for the on-board flash of the Technologic
System's TS-5500 board. The flash is split into 3 partitions
which are accessed as separate MTD devices.
mtd0 and mtd2 are the two BIOS drives. Unfortunately the BIOS
uses a proprietary flash translation layer from General Software,
which is not supported (the drives cannot be mounted). You can
create your own file system (jffs for example), but the BIOS
won't be able to boot from it.
mtd1 allows you to reprogram your BIOS. BE VERY CAREFUL.
Note that jumper 3 ("Write Enable Drive A") must be set
otherwise detection won't succeeed.
config MTD_SBC_GXX
tristate "CFI Flash device mapped on Arcom SBC-GXx boards"
depends on X86 && MTD_CFI_INTELEXT && MTD_PARTITIONS && MTD_COMPLEX_MAPPINGS
help
This provides a driver for the on-board flash of Arcom Control
Systems' SBC-GXn family of boards, formerly known as SBC-MediaGX.
By default the flash is split into 3 partitions which are accessed
as separate MTD devices. This board utilizes Intel StrataFlash.
More info at
<http://www.arcomcontrols.com/products/icp/pc104/processors/SBC_GX1.htm>.
config MTD_ELAN_104NC
tristate "CFI Flash device mapped on Arcom ELAN-104NC"
depends on X86 && MTD_CFI_INTELEXT && MTD_PARTITIONS && MTD_COMPLEX_MAPPINGS
help
This provides a driver for the on-board flash of the Arcom Control
System's ELAN-104NC development board. By default the flash
is split into 3 partitions which are accessed as separate MTD
devices. This board utilizes Intel StrataFlash. More info at
<http://www.arcomcontrols.com/products/icp/pc104/processors/ELAN104NC.htm>.
config MTD_LUBBOCK
tristate "CFI Flash device mapped on Intel Lubbock XScale eval board"
depends on ARCH_LUBBOCK && MTD_CFI_INTELEXT && MTD_PARTITIONS
help
This provides a driver for the on-board flash of the Intel
'Lubbock' XScale evaluation board.
config MTD_OCTAGON
tristate "JEDEC Flash device mapped on Octagon 5066 SBC"
depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS
help
This provides a 'mapping' driver which supports the way in which
the flash chips are connected in the Octagon-5066 Single Board
Computer. More information on the board is available at
<http://www.octagonsystems.com/CPUpages/5066.html>.
config MTD_VMAX
tristate "JEDEC Flash device mapped on Tempustech VMAX SBC301"
depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS
help
This provides a 'mapping' driver which supports the way in which
the flash chips are connected in the Tempustech VMAX SBC301 Single
Board Computer. More information on the board is available at
<http://www.tempustech.com/>.
config MTD_SCx200_DOCFLASH
tristate "Flash device mapped with DOCCS on NatSemi SCx200"
depends on SCx200 && MTD_CFI && MTD_PARTITIONS
help
Enable support for a flash chip mapped using the DOCCS signal on a
National Semiconductor SCx200 processor.
If you don't know what to do here, say N.
If compiled as a module, it will be called scx200_docflash.
config MTD_AMD76XROM
tristate "BIOS flash chip on AMD76x southbridge"
depends on X86 && MTD_JEDECPROBE
help
Support for treating the BIOS flash chip on AMD76x motherboards
as an MTD device - with this you can reprogram your BIOS.
BE VERY CAREFUL.
config MTD_ICHXROM
tristate "BIOS flash chip on Intel Controller Hub 2/3/4/5"
depends on X86 && MTD_JEDECPROBE
help
Support for treating the BIOS flash chip on ICHX motherboards
as an MTD device - with this you can reprogram your BIOS.
BE VERY CAREFUL.
config MTD_SCB2_FLASH
tristate "BIOS flash chip on Intel SCB2 boards"
depends on X86 && MTD_JEDECPROBE
help
Support for treating the BIOS flash chip on Intel SCB2 boards
as an MTD device - with this you can reprogram your BIOS.
BE VERY CAREFUL.
config MTD_TSUNAMI
tristate "Flash chips on Tsunami TIG bus"
depends on ALPHA_TSUNAMI && MTD_COMPLEX_MAPPINGS
help
Support for the flash chip on Tsunami TIG bus.
config MTD_LASAT
tristate "Flash chips on LASAT board"
depends on LASAT
help
Support for the flash chips on the Lasat 100 and 200 boards.
config MTD_NETtel
tristate "CFI flash device on SnapGear/SecureEdge"
depends on X86 && MTD_PARTITIONS && MTD_JEDECPROBE
help
Support for flash chips on NETtel/SecureEdge/SnapGear boards.
config MTD_PB1XXX
tristate "Flash devices on Alchemy PB1xxx boards"
depends on MIPS && ( MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 )
help
Flash memory access on Alchemy Pb1000/Pb1100/Pb1500 boards
config MTD_PB1XXX_BOOT
bool "PB1x00 boot flash device"
depends on MTD_PB1XXX && ( MIPS_PB1100 || MIPS_PB1500 )
help
Use the first of the two 32MiB flash banks on Pb1100/Pb1500 board.
You can say 'Y' to both this and 'MTD_PB1XXX_USER' below, to use
both banks.
config MTD_PB1XXX_USER
bool "PB1x00 user flash device"
depends on MTD_PB1XXX && ( MIPS_PB1100 || MIPS_PB1500 )
default y if MTD_PB1XX_BOOT = n
help
Use the second of the two 32MiB flash banks on Pb1100/Pb1500 board.
You can say 'Y' to both this and 'MTD_PB1XXX_BOOT' above, to use
both banks.
config MTD_PB1550
tristate "Flash devices on Alchemy PB1550 board"
depends on MIPS && MIPS_PB1550
help
Flash memory access on Alchemy Pb1550 board
config MTD_PB1550_BOOT
bool "PB1550 boot flash device"
depends on MTD_PB1550
help
Use the first of the two 64MiB flash banks on Pb1550 board.
You can say 'Y' to both this and 'MTD_PB1550_USER' below, to use
both banks.
config MTD_PB1550_USER
bool "PB1550 user flash device"
depends on MTD_PB1550
default y if MTD_PB1550_BOOT = n
help
Use the second of the two 64MiB flash banks on Pb1550 board.
You can say 'Y' to both this and 'MTD_PB1550_BOOT' above, to use
both banks.
config MTD_DB1550
tristate "Flash devices on Alchemy DB1550 board"
depends on MIPS && MIPS_DB1550
help
Flash memory access on Alchemy Db1550 board
config MTD_DB1550_BOOT
bool "DB1550 boot flash device"
depends on MTD_DB1550
help
Use the first of the two 64MiB flash banks on Db1550 board.
You can say 'Y' to both this and 'MTD_DB1550_USER' below, to use
both banks.
config MTD_DB1550_USER
bool "DB1550 user flash device"
depends on MTD_DB1550
default y if MTD_DB1550_BOOT = n
help
Use the second of the two 64MiB flash banks on Db1550 board.
You can say 'Y' to both this and 'MTD_DB1550_BOOT' above, to use
both banks.
config MTD_DILNETPC
tristate "CFI Flash device mapped on DIL/Net PC"
depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT
help
MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP".
For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm>
and <http://www.ssv-embedded.de/ssv/pc104/p170.htm>
config MTD_DILNETPC_BOOTSIZE
hex "Size of DIL/Net PC flash boot partition"
depends on MTD_DILNETPC
default "0x80000"
help
The amount of space taken up by the kernel or Etherboot
on the DIL/Net PC flash chips.
config MTD_L440GX
tristate "BIOS flash chip on Intel L440GX boards"
depends on X86 && MTD_JEDECPROBE
help
Support for treating the BIOS flash chip on Intel L440GX motherboards
as an MTD device - with this you can reprogram your BIOS.
BE VERY CAREFUL.
config MTD_SBC8240
tristate "Flash device on SBC8240"
depends on PPC32 && MTD_JEDECPROBE && 6xx && 8260
help
Flash access on the SBC8240 board from Wind River. See
<http://www.windriver.com/products/sbc8240/>
config MTD_TQM8XXL
tristate "CFI Flash device mapped on TQM8XXL"
depends on MTD_CFI && PPC32 && 8xx && TQM8xxL
help
The TQM8xxL PowerPC board has up to two banks of CFI-compliant
chips, currently uses AMD one. This 'mapping' driver supports
that arrangement, allowing the CFI probe and command set driver
code to communicate with the chips on the TQM8xxL board. More at
<http://www.denx.de/embedded-ppc-en.html>.
config MTD_RPXLITE
tristate "CFI Flash device mapped on RPX Lite or CLLF"
depends on MTD_CFI && PPC32 && 8xx && (RPXCLASSIC || RPXLITE)
help
The RPXLite PowerPC board has CFI-compliant chips mapped in
a strange sparse mapping. This 'mapping' driver supports that
arrangement, allowing the CFI probe and command set driver code
to communicate with the chips on the RPXLite board. More at
<http://www.embeddedplanet.com/>.
config MTD_MBX860
tristate "System flash on MBX860 board"
depends on MTD_CFI && PPC32 && 8xx && MBX
help
This enables access routines for the flash chips on the Motorola
MBX860 board. If you have one of these boards and would like
to use the flash chips on it, say 'Y'.
config MTD_DBOX2
tristate "CFI Flash device mapped on D-Box2"
depends on PPC32 && 8xx && DBOX2 && MTD_CFI_INTELSTD && MTD_CFI_INTELEXT && MTD_CFI_AMDSTD
help
This enables access routines for the flash chips on the Nokia/Sagem
D-Box 2 board. If you have one of these boards and would like to use
the flash chips on it, say 'Y'.
config MTD_CFI_FLAGADM
tristate "CFI Flash device mapping on FlagaDM"
depends on PPC32 && 8xx && MTD_CFI
help
Mapping for the Flaga digital module. If you don't have one, ignore
this setting.
config MTD_BEECH
tristate "CFI Flash device mapped on IBM 405LP Beech"
depends on MTD_CFI && PPC32 && 40x && BEECH
help
This enables access routines for the flash chips on the IBM
405LP Beech board. If you have one of these boards and would like
to use the flash chips on it, say 'Y'.
config MTD_ARCTIC
tristate "CFI Flash device mapped on IBM 405LP Arctic"
depends on MTD_CFI && PPC32 && 40x && ARCTIC2
help
This enables access routines for the flash chips on the IBM 405LP
Arctic board. If you have one of these boards and would like to
use the flash chips on it, say 'Y'.
config MTD_WALNUT
tristate "Flash device mapped on IBM 405GP Walnut"
depends on MTD_JEDECPROBE && PPC32 && 40x && WALNUT
help
This enables access routines for the flash chips on the IBM 405GP
Walnut board. If you have one of these boards and would like to
use the flash chips on it, say 'Y'.
config MTD_EBONY
tristate "Flash devices mapped on IBM 440GP Ebony"
depends on MTD_JEDECPROBE && PPC32 && 44x && EBONY
help
This enables access routines for the flash chips on the IBM 440GP
Ebony board. If you have one of these boards and would like to
use the flash chips on it, say 'Y'.
config MTD_OCOTEA
tristate "Flash devices mapped on IBM 440GX Ocotea"
depends on MTD_CFI && PPC32 && 44x && OCOTEA
help
This enables access routines for the flash chips on the IBM 440GX
Ocotea board. If you have one of these boards and would like to
use the flash chips on it, say 'Y'.
config MTD_REDWOOD
tristate "CFI Flash devices mapped on IBM Redwood"
depends on MTD_CFI && PPC32 && 4xx && 40x && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 )
help
This enables access routines for the flash chips on the IBM
Redwood board. If you have one of these boards and would like to
use the flash chips on it, say 'Y'.
config MTD_CSTM_MIPS_IXX
tristate "Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board"
depends on MIPS && MTD_CFI && MTD_JEDECPROBE && MTD_PARTITIONS
help
This provides a mapping driver for the Integrated Technology
Express, Inc (ITE) QED-4N-S01B eval board and the Globespan IVR
Reference Board. It provides the necessary addressing, length,
buswidth, vpp code and addition setup of the flash device for
these boards. In addition, this mapping driver can be used for
other boards via setting of the CONFIG_MTD_CSTM_MIPS_IXX_START/
LEN/BUSWIDTH parameters. This mapping will provide one mtd device
using one partition. The start address can be offset from the
beginning of flash and the len can be less than the total flash
device size to allow a window into the flash. Both CFI and JEDEC
probes are called.
config MTD_CSTM_MIPS_IXX_START
hex "Physical start address of flash mapping"
depends on MTD_CSTM_MIPS_IXX
default "0x8000000"
help
This is the physical memory location that the MTD driver will
use for the flash chips on your particular target board.
Refer to the memory map which should hopefully be in the
documentation for your board.
config MTD_CSTM_MIPS_IXX_LEN
hex "Physical length of flash mapping"
depends on MTD_CSTM_MIPS_IXX
default "0x4000000"
help
This is the total length that the MTD driver will use for the
flash chips on your particular board. Refer to the memory
map which should hopefully be in the documentation for your
board.
config MTD_CSTM_MIPS_IXX_BUSWIDTH
int "Bus width in octets"
depends on MTD_CSTM_MIPS_IXX
default "2"
help
This is the total bus width of the mapping of the flash chips
on your particular board.
config MTD_OCELOT
tristate "Momenco Ocelot boot flash device"
depends on MIPS && MOMENCO_OCELOT
help
This enables access routines for the boot flash device and for the
NVRAM on the Momenco Ocelot board. If you have one of these boards
and would like access to either of these, say 'Y'.
config MTD_SOLUTIONENGINE
tristate "CFI Flash device mapped on Hitachi SolutionEngine"
depends on SUPERH && MTD_CFI && MTD_REDBOOT_PARTS
help
This enables access to the flash chips on the Hitachi SolutionEngine and
similar boards. Say 'Y' if you are building a kernel for such a board.
config MTD_ARM_INTEGRATOR
tristate "CFI Flash device mapped on ARM Integrator/P720T"
depends on ARM && MTD_CFI
config MTD_CDB89712
tristate "Cirrus CDB89712 evaluation board mappings"
depends on ARM && MTD_CFI && ARCH_CDB89712
help
This enables access to the flash or ROM chips on the CDB89712 board.
If you have such a board, say 'Y'.
config MTD_SA1100
tristate "CFI Flash device mapped on StrongARM SA11x0"
depends on ARM && MTD_CFI && ARCH_SA1100 && MTD_PARTITIONS
help
This enables access to the flash chips on most platforms based on
the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
If you have such a board, say 'Y'.
config MTD_IPAQ
tristate "CFI Flash device mapped on Compaq/HP iPAQ"
depends on ARM && IPAQ_HANDHELD && MTD_CFI
help
This provides a driver for the on-board flash of the iPAQ.
config MTD_DC21285
tristate "CFI Flash device mapped on DC21285 Footbridge"
depends on ARM && MTD_CFI && ARCH_FOOTBRIDGE && MTD_COMPLEX_MAPPINGS
help
This provides a driver for the flash accessed using Intel's
21285 bridge used with Intel's StrongARM processors. More info at
<http://www.intel.com/design/bridge/docs/21285_documentation.htm>.
config MTD_IQ80310
tristate "CFI Flash device mapped on the XScale IQ80310 board"
depends on ARM && MTD_CFI && ARCH_IQ80310
help
This enables access routines for the flash chips on the Intel XScale
IQ80310 evaluation board. If you have one of these boards and would
like to use the flash chips on it, say 'Y'.
config MTD_IXP4XX
tristate "CFI Flash device mapped on Intel IXP4xx based systems"
depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX
help
This enables MTD access to flash devices on platforms based
on Intel's IXP4xx family of network processors such as the
IXDP425 and Coyote. If you have an IXP4xx based board and
would like to use the flash chips on it, say 'Y'.
config MTD_IXP2000
tristate "CFI Flash device mapped on Intel IXP2000 based systems"
depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000
help
This enables MTD access to flash devices on platforms based
on Intel's IXP2000 family of network processors such as the
IXDP425 and Coyote. If you have an IXP2000 based board and
would like to use the flash chips on it, say 'Y'.
config MTD_EPXA10DB
tristate "CFI Flash device mapped on Epxa10db"
depends on ARM && MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT
help
This enables support for the flash devices on the Altera
Excalibur XA10 Development Board. If you are building a kernel
for on of these boards then you should say 'Y' otherwise say 'N'.
config MTD_FORTUNET
tristate "CFI Flash device mapped on the FortuNet board"
depends on ARM && MTD_CFI && MTD_PARTITIONS && SA1100_FORTUNET
help
This enables access to the Flash on the FortuNet board. If you
have such a board, say 'Y'.
config MTD_AUTCPU12
tristate "NV-RAM mapping AUTCPU12 board"
depends on ARM && ARCH_AUTCPU12
help
This enables access to the NV-RAM on autronix autcpu12 board.
If you have such a board, say 'Y'.
config MTD_EDB7312
tristate "CFI Flash device mapped on EDB7312"
depends on ARM && MTD_CFI
help
This enables access to the CFI Flash on the Cogent EDB7312 board.
If you have such a board, say 'Y' here.
config MTD_IMPA7
tristate "JEDEC Flash device mapped on impA7"
depends on ARM && MTD_JEDECPROBE
help
This enables access to the NOR Flash on the impA7 board of
implementa GmbH. If you have such a board, say 'Y' here.
config MTD_CEIVA
tristate "JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame"
depends on ARM && MTD_JEDECPROBE && ARCH_CEIVA
help
This enables access to the flash chips on the Ceiva/Polaroid
PhotoMax Digital Picture Frame.
If you have such a device, say 'Y'.
config MTD_NOR_TOTO
tristate "NOR Flash device on TOTO board"
depends on ARM && ARCH_OMAP && OMAP_TOTO
help
This enables access to the NOR flash on the Texas Instruments
TOTO board.
config MTD_H720X
tristate "Hynix evaluation board mappings"
depends on ARM && MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
help
This enables access to the flash chips on the Hynix evaluation boards.
If you have such a board, say 'Y'.
config MTD_MPC1211
tristate "CFI Flash device mapped on Interface MPC-1211"
depends on SUPERH && SH_MPC1211 && MTD_CFI
help
This enables access to the flash chips on the Interface MPC-1211(CTP/PCI/MPC-SH02).
If you have such a board, say 'Y'.
# This needs CFI or JEDEC, depending on the cards found.
config MTD_PCI
tristate "PCI MTD driver"
depends on MTD && PCI && MTD_COMPLEX_MAPPINGS
help
Mapping for accessing flash devices on add-in cards like the Intel XScale
IQ80310 card, and the Intel EBSA285 card in blank ROM programming mode
(please see the manual for the link settings).
If you are not sure, say N.
config MTD_PCMCIA
tristate "PCMCIA MTD driver"
depends on MTD && PCMCIA && MTD_COMPLEX_MAPPINGS && BROKEN
help
Map driver for accessing PCMCIA linear flash memory cards. These
cards are usually around 4-16MiB in size. This does not include
Compact Flash cards which are treated as IDE devices.
config MTD_UCLINUX
tristate "Generic uClinux RAM/ROM filesystem support"
depends on MTD_PARTITIONS && !MMU
help
Map driver to support image based filesystems for uClinux.
config MTD_WRSBC8260
tristate "Map driver for WindRiver PowerQUICC II MPC82xx board"
depends on (SBC82xx || SBC8560)
select MTD_PARTITIONS
select MTD_MAP_BANK_WIDTH_4
select MTD_MAP_BANK_WIDTH_1
select MTD_CFI_I1
select MTD_CFI_I4
help
Map driver for WindRiver PowerQUICC II MPC82xx board. Drives
all three flash regions on CS0, CS1 and CS6 if they are configured
correctly by the boot loader.
config MTD_DMV182
tristate "Map driver for Dy-4 SVME/DMV-182 board."
depends on DMV182
select MTD_PARTITIONS
select MTD_MAP_BANK_WIDTH_32
select MTD_CFI_I8
select MTD_CFI_AMDSTD
help
Map driver for Dy-4 SVME/DMV-182 board.
config MTD_BAST
tristate "Map driver for Simtec BAST (EB2410ITX)"
depends on ARCH_BAST
select MTD_PARTITIONS
select MTD_MAP_BANK_WIDTH_16
select MTD_JEDECPROBE
help
Map driver for NOR flash on the Simtec BAST (EB2410ITX).
Note, this driver *cannot* over-ride the WP link on the
board, or currently detect the state of the link.
config MTD_BAST_MAXSIZE
int "Maximum size for BAST flash area (MiB)"
depends on MTD_BAST
default "4"
config MTD_SHARP_SL
bool "ROM maped on Sharp SL Series"
depends on MTD && ARCH_PXA
help
This enables access to the flash chip on the Sharp SL Series of PDAs.
endmenu

73
drivers/mtd/maps/Makefile ノーマルファイル
ファイルの表示

@@ -0,0 +1,73 @@
#
# linux/drivers/maps/Makefile
#
# $Id: Makefile.common,v 1.23 2005/01/05 17:06:36 dwmw2 Exp $
ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y)
obj-$(CONFIG_MTD) += map_funcs.o
endif
# Chip mappings
obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
obj-$(CONFIG_MTD_BAST) += bast-flash.o
obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o
obj-$(CONFIG_MTD_DC21285) += dc21285.o
obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o
obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o
obj-$(CONFIG_MTD_IQ80310) += iq80310.o
obj-$(CONFIG_MTD_L440GX) += l440gx.o
obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o
obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o
obj-$(CONFIG_MTD_MBX860) += mbx860.o
obj-$(CONFIG_MTD_CEIVA) += ceiva.o
obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
obj-$(CONFIG_MTD_IPAQ) += ipaq-flash.o
obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o
obj-$(CONFIG_MTD_NETSC520) += netsc520.o
obj-$(CONFIG_MTD_TS5500) += ts5500_flash.o
obj-$(CONFIG_MTD_SUN_UFLASH) += sun_uflash.o
obj-$(CONFIG_MTD_VMAX) += vmax301.o
obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o
obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.o
obj-$(CONFIG_MTD_OCELOT) += ocelot.o
obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
obj-$(CONFIG_MTD_PCI) += pci.o
obj-$(CONFIG_MTD_PB1XXX) += pb1xxx-flash.o
obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o
obj-$(CONFIG_MTD_PB1550) += pb1550-flash.o
obj-$(CONFIG_MTD_DB1550) += db1550-flash.o
obj-$(CONFIG_MTD_LASAT) += lasat.o
obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
obj-$(CONFIG_MTD_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_IMPA7) += impa7.o
obj-$(CONFIG_MTD_FORTUNET) += fortunet.o
obj-$(CONFIG_MTD_REDWOOD) += redwood.o
obj-$(CONFIG_MTD_UCLINUX) += uclinux.o
obj-$(CONFIG_MTD_NETtel) += nettel.o
obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o
obj-$(CONFIG_MTD_EBONY) += ebony.o
obj-$(CONFIG_MTD_OCOTEA) += ocotea.o
obj-$(CONFIG_MTD_BEECH) += beech-mtd.o
obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o
obj-$(CONFIG_MTD_WALNUT) += walnut.o
obj-$(CONFIG_MTD_H720X) += h720x-flash.o
obj-$(CONFIG_MTD_SBC8240) += sbc8240.o
obj-$(CONFIG_MTD_NOR_TOTO) += omap-toto-flash.o
obj-$(CONFIG_MTD_MPC1211) += mpc1211.o
obj-$(CONFIG_MTD_IXP4XX) += ixp4xx.o
obj-$(CONFIG_MTD_IXP2000) += ixp2000.o
obj-$(CONFIG_MTD_WRSBC8260) += wr_sbc82xx_flash.o
obj-$(CONFIG_MTD_DMV182) += dmv182.o
obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o

332
drivers/mtd/maps/amd76xrom.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,332 @@
/*
* amd76xrom.c
*
* Normal mappings of chips in physical memory
* $Id: amd76xrom.c,v 1.19 2004/11/28 09:40:39 dwmw2 Exp $
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/cfi.h>
#include <linux/mtd/flashchip.h>
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/list.h>
#define xstr(s) str(s)
#define str(s) #s
#define MOD_NAME xstr(KBUILD_BASENAME)
#define ADDRESS_NAME_LEN 18
#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
struct amd76xrom_window {
void __iomem *virt;
unsigned long phys;
unsigned long size;
struct list_head maps;
struct resource rsrc;
struct pci_dev *pdev;
};
struct amd76xrom_map_info {
struct list_head list;
struct map_info map;
struct mtd_info *mtd;
struct resource rsrc;
char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
};
static struct amd76xrom_window amd76xrom_window = {
.maps = LIST_HEAD_INIT(amd76xrom_window.maps),
};
static void amd76xrom_cleanup(struct amd76xrom_window *window)
{
struct amd76xrom_map_info *map, *scratch;
u8 byte;
if (window->pdev) {
/* Disable writes through the rom window */
pci_read_config_byte(window->pdev, 0x40, &byte);
pci_write_config_byte(window->pdev, 0x40, byte & ~1);
}
/* Free all of the mtd devices */
list_for_each_entry_safe(map, scratch, &window->maps, list) {
if (map->rsrc.parent) {
release_resource(&map->rsrc);
}
del_mtd_device(map->mtd);
map_destroy(map->mtd);
list_del(&map->list);
kfree(map);
}
if (window->rsrc.parent)
release_resource(&window->rsrc);
if (window->virt) {
iounmap(window->virt);
window->virt = NULL;
window->phys = 0;
window->size = 0;
window->pdev = NULL;
}
}
static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
u8 byte;
struct amd76xrom_window *window = &amd76xrom_window;
struct amd76xrom_map_info *map = NULL;
unsigned long map_top;
/* Remember the pci dev I find the window in */
window->pdev = pdev;
/* Assume the rom window is properly setup, and find it's size */
pci_read_config_byte(pdev, 0x43, &byte);
if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) {
window->phys = 0xffb00000; /* 5MiB */
}
else if ((byte & (1<<7)) == (1<<7)) {
window->phys = 0xffc00000; /* 4MiB */
}
else {
window->phys = 0xffff0000; /* 64KiB */
}
window->size = 0xffffffffUL - window->phys + 1UL;
/*
* Try to reserve the window mem region. If this fails then
* it is likely due to a fragment of the window being
* "reseved" by the BIOS. In the case that the
* request_mem_region() fails then once the rom size is
* discovered we will try to reserve the unreserved fragment.
*/
window->rsrc.name = MOD_NAME;
window->rsrc.start = window->phys;
window->rsrc.end = window->phys + window->size - 1;
window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
if (request_resource(&iomem_resource, &window->rsrc)) {
window->rsrc.parent = NULL;
printk(KERN_ERR MOD_NAME
" %s(): Unable to register resource"
" 0x%.08lx-0x%.08lx - kernel bug?\n",
__func__,
window->rsrc.start, window->rsrc.end);
}
#if 0
/* Enable the selected rom window */
pci_read_config_byte(pdev, 0x43, &byte);
pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits);
#endif
/* Enable writes through the rom window */
pci_read_config_byte(pdev, 0x40, &byte);
pci_write_config_byte(pdev, 0x40, byte | 1);
/* FIXME handle registers 0x80 - 0x8C the bios region locks */
/* For write accesses caches are useless */
window->virt = ioremap_nocache(window->phys, window->size);
if (!window->virt) {
printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
window->phys, window->size);
goto out;
}
/* Get the first address to look for an rom chip at */
map_top = window->phys;
#if 1
/* The probe sequence run over the firmware hub lock
* registers sets them to 0x7 (no access).
* Probe at most the last 4M of the address space.
*/
if (map_top < 0xffc00000) {
map_top = 0xffc00000;
}
#endif
/* Loop through and look for rom chips */
while((map_top - 1) < 0xffffffffUL) {
struct cfi_private *cfi;
unsigned long offset;
int i;
if (!map) {
map = kmalloc(sizeof(*map), GFP_KERNEL);
}
if (!map) {
printk(KERN_ERR MOD_NAME ": kmalloc failed");
goto out;
}
memset(map, 0, sizeof(*map));
INIT_LIST_HEAD(&map->list);
map->map.name = map->map_name;
map->map.phys = map_top;
offset = map_top - window->phys;
map->map.virt = (void __iomem *)
(((unsigned long)(window->virt)) + offset);
map->map.size = 0xffffffffUL - map_top + 1UL;
/* Set the name of the map to the address I am trying */
sprintf(map->map_name, "%s @%08lx",
MOD_NAME, map->map.phys);
/* There is no generic VPP support */
for(map->map.bankwidth = 32; map->map.bankwidth;
map->map.bankwidth >>= 1)
{
char **probe_type;
/* Skip bankwidths that are not supported */
if (!map_bankwidth_supported(map->map.bankwidth))
continue;
/* Setup the map methods */
simple_map_init(&map->map);
/* Try all of the probe methods */
probe_type = rom_probe_types;
for(; *probe_type; probe_type++) {
map->mtd = do_map_probe(*probe_type, &map->map);
if (map->mtd)
goto found;
}
}
map_top += ROM_PROBE_STEP_SIZE;
continue;
found:
/* Trim the size if we are larger than the map */
if (map->mtd->size > map->map.size) {
printk(KERN_WARNING MOD_NAME
" rom(%u) larger than window(%lu). fixing...\n",
map->mtd->size, map->map.size);
map->mtd->size = map->map.size;
}
if (window->rsrc.parent) {
/*
* Registering the MTD device in iomem may not be possible
* if there is a BIOS "reserved" and BUSY range. If this
* fails then continue anyway.
*/
map->rsrc.name = map->map_name;
map->rsrc.start = map->map.phys;
map->rsrc.end = map->map.phys + map->mtd->size - 1;
map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
if (request_resource(&window->rsrc, &map->rsrc)) {
printk(KERN_ERR MOD_NAME
": cannot reserve MTD resource\n");
map->rsrc.parent = NULL;
}
}
/* Make the whole region visible in the map */
map->map.virt = window->virt;
map->map.phys = window->phys;
cfi = map->map.fldrv_priv;
for(i = 0; i < cfi->numchips; i++) {
cfi->chips[i].start += offset;
}
/* Now that the mtd devices is complete claim and export it */
map->mtd->owner = THIS_MODULE;
if (add_mtd_device(map->mtd)) {
map_destroy(map->mtd);
map->mtd = NULL;
goto out;
}
/* Calculate the new value of map_top */
map_top += map->mtd->size;
/* File away the map structure */
list_add(&map->list, &window->maps);
map = NULL;
}
out:
/* Free any left over map structures */
if (map) {
kfree(map);
}
/* See if I have any map structures */
if (list_empty(&window->maps)) {
amd76xrom_cleanup(window);
return -ENODEV;
}
return 0;
}
static void __devexit amd76xrom_remove_one (struct pci_dev *pdev)
{
struct amd76xrom_window *window = &amd76xrom_window;
amd76xrom_cleanup(window);
}
static struct pci_device_id amd76xrom_pci_tbl[] = {
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7440,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_AMD, 0x7468 }, /* amd8111 support */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, amd76xrom_pci_tbl);
#if 0
static struct pci_driver amd76xrom_driver = {
.name = MOD_NAME,
.id_table = amd76xrom_pci_tbl,
.probe = amd76xrom_init_one,
.remove = amd76xrom_remove_one,
};
#endif
static int __init init_amd76xrom(void)
{
struct pci_dev *pdev;
struct pci_device_id *id;
pdev = NULL;
for(id = amd76xrom_pci_tbl; id->vendor; id++) {
pdev = pci_find_device(id->vendor, id->device, NULL);
if (pdev) {
break;
}
}
if (pdev) {
return amd76xrom_init_one(pdev, &amd76xrom_pci_tbl[0]);
}
return -ENXIO;
#if 0
return pci_module_init(&amd76xrom_driver);
#endif
}
static void __exit cleanup_amd76xrom(void)
{
amd76xrom_remove_one(amd76xrom_window.pdev);
}
module_init(init_amd76xrom);
module_exit(cleanup_amd76xrom);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
MODULE_DESCRIPTION("MTD map driver for BIOS chips on the AMD76X southbridge");

135
drivers/mtd/maps/arctic-mtd.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,135 @@
/*
* $Id: arctic-mtd.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $
*
* drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for
* IBM 405LP Arctic boards.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Copyright (C) 2002, International Business Machines Corporation
* All Rights Reserved.
*
* Bishop Brock
* IBM Research, Austin Center for Low-Power Computing
* bcbrock@us.ibm.com
* March 2002
*
* modified for Arctic by,
* David Gibson
* IBM OzLabs, Canberra, Australia
* <arctic@gibson.dropbear.id.au>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/ibm4xx.h>
/*
* 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB)
* 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB)
* 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP)
* 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB)
*/
#define FFS1_SIZE 0x01000000 /* 16MiB */
#define KERNEL_SIZE 0x00500000 /* 5.12MiB */
#define FFS2_SIZE 0x00a60000 /* 10.624MiB */
#define FIRMWARE_SIZE 0x000a0000 /* 640KiB */
#define NAME "Arctic Linux Flash"
#define PADDR SUBZERO_BOOTFLASH_PADDR
#define BUSWIDTH 2
#define SIZE SUBZERO_BOOTFLASH_SIZE
#define PARTITIONS 4
/* Flash memories on these boards are memory resources, accessed big-endian. */
{
/* do nothing for now */
}
static struct map_info arctic_mtd_map = {
.name = NAME,
.size = SIZE,
.bankwidth = BUSWIDTH,
.phys = PADDR,
};
static struct mtd_info *arctic_mtd;
static struct mtd_partition arctic_partitions[PARTITIONS] = {
{ .name = "Filesystem",
.size = FFS1_SIZE,
.offset = 0,},
{ .name = "Kernel",
.size = KERNEL_SIZE,
.offset = FFS1_SIZE,},
{ .name = "Filesystem",
.size = FFS2_SIZE,
.offset = FFS1_SIZE + KERNEL_SIZE,},
{ .name = "Firmware",
.size = FIRMWARE_SIZE,
.offset = SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,},
};
static int __init
init_arctic_mtd(void)
{
printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
arctic_mtd_map.virt = ioremap(PADDR, SIZE);
if (!arctic_mtd_map.virt) {
printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
return -EIO;
}
simple_map_init(&arctic_mtd_map);
printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map);
if (!arctic_mtd)
return -ENXIO;
arctic_mtd->owner = THIS_MODULE;
return add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS);
}
static void __exit
cleanup_arctic_mtd(void)
{
if (arctic_mtd) {
del_mtd_partitions(arctic_mtd);
map_destroy(arctic_mtd);
iounmap((void *) arctic_mtd_map.virt);
}
}
module_init(init_arctic_mtd);
module_exit(cleanup_arctic_mtd);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Gibson <arctic@gibson.dropbear.id.au>");
MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Arctic boards");

127
drivers/mtd/maps/autcpu12-nvram.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,127 @@
/*
* NV-RAM memory access on autcpu12
* (C) 2002 Thomas Gleixner (gleixner@autronix.de)
*
* $Id: autcpu12-nvram.c,v 1.8 2004/11/04 13:24:14 gleixner Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/sizes.h>
#include <asm/hardware.h>
#include <asm/arch/autcpu12.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
static struct mtd_info *sram_mtd;
struct map_info autcpu12_sram_map = {
.name = "SRAM",
.size = 32768,
.bankwidth = 4,
.phys = 0x12000000,
};
static int __init init_autcpu12_sram (void)
{
int err, save0, save1;
autcpu12_sram_map.virt = ioremap(0x12000000, SZ_128K);
if (!autcpu12_sram_map.virt) {
printk("Failed to ioremap autcpu12 NV-RAM space\n");
err = -EIO;
goto out;
}
simple_map_init(&autcpu_sram_map);
/*
* Check for 32K/128K
* read ofs 0
* read ofs 0x10000
* Write complement to ofs 0x100000
* Read and check result on ofs 0x0
* Restore contents
*/
save0 = map_read32(&autcpu12_sram_map,0);
save1 = map_read32(&autcpu12_sram_map,0x10000);
map_write32(&autcpu12_sram_map,~save0,0x10000);
/* if we find this pattern on 0x0, we have 32K size
* restore contents and exit
*/
if ( map_read32(&autcpu12_sram_map,0) != save0) {
map_write32(&autcpu12_sram_map,save0,0x0);
goto map;
}
/* We have a 128K found, restore 0x10000 and set size
* to 128K
*/
map_write32(&autcpu12_sram_map,save1,0x10000);
autcpu12_sram_map.size = SZ_128K;
map:
sram_mtd = do_map_probe("map_ram", &autcpu12_sram_map);
if (!sram_mtd) {
printk("NV-RAM probe failed\n");
err = -ENXIO;
goto out_ioremap;
}
sram_mtd->owner = THIS_MODULE;
sram_mtd->erasesize = 16;
if (add_mtd_device(sram_mtd)) {
printk("NV-RAM device addition failed\n");
err = -ENOMEM;
goto out_probe;
}
printk("NV-RAM device size %ldKiB registered on AUTCPU12\n",autcpu12_sram_map.size/SZ_1K);
return 0;
out_probe:
map_destroy(sram_mtd);
sram_mtd = 0;
out_ioremap:
iounmap((void *)autcpu12_sram_map.virt);
out:
return err;
}
static void __exit cleanup_autcpu12_maps(void)
{
if (sram_mtd) {
del_mtd_device(sram_mtd);
map_destroy(sram_mtd);
iounmap((void *)autcpu12_sram_map.virt);
}
}
module_init(init_autcpu12_sram);
module_exit(cleanup_autcpu12_maps);
MODULE_AUTHOR("Thomas Gleixner");
MODULE_DESCRIPTION("autcpu12 NV-RAM map driver");
MODULE_LICENSE("GPL");

227
drivers/mtd/maps/bast-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,227 @@
/* linux/drivers/mtd/maps/bast_flash.c
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Simtec Bast (EB2410ITX) NOR MTD Mapping driver
*
* Changelog:
* 20-Sep-2004 BJD Initial version
*
* $Id: bast-flash.c,v 1.1 2004/09/21 14:29:04 bjd Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/mach/flash.h>
#include <asm/arch/map.h>
#include <asm/arch/bast-map.h>
#include <asm/arch/bast-cpld.h>
#ifdef CONFIG_MTD_BAST_MAXSIZE
#define AREA_MAXSIZE (CONFIG_MTD_BAST_MAXSIZE * (1024*1024))
#else
#define AREA_MAXSIZE (32*1024*1024)
#endif
#define PFX "bast-flash: "
struct bast_flash_info {
struct mtd_info *mtd;
struct map_info map;
struct mtd_partition *partitions;
struct resource *area;
};
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
static struct bast_flash_info *to_bast_info(struct device *dev)
{
return (struct bast_flash_info *)dev_get_drvdata(dev);
}
static void bast_flash_setrw(int to)
{
unsigned int val;
unsigned long flags;
local_irq_save(flags);
val = __raw_readb(BAST_VA_CTRL3);
if (to)
val |= BAST_CPLD_CTRL3_ROMWEN;
else
val &= ~BAST_CPLD_CTRL3_ROMWEN;
pr_debug("new cpld ctrl3=%02x\n", val);
__raw_writeb(val, BAST_VA_CTRL3);
local_irq_restore(flags);
}
static int bast_flash_remove(struct device *dev)
{
struct bast_flash_info *info = to_bast_info(dev);
dev_set_drvdata(dev, NULL);
if (info == NULL)
return 0;
if (info->map.virt != NULL)
iounmap(info->map.virt);
if (info->mtd) {
del_mtd_partitions(info->mtd);
map_destroy(info->mtd);
}
if (info->partitions)
kfree(info->partitions);
if (info->area) {
release_resource(info->area);
kfree(info->area);
}
kfree(info);
return 0;
}
static int bast_flash_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct bast_flash_info *info;
struct resource *res;
int err = 0;
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL) {
printk(KERN_ERR PFX "no memory for flash info\n");
err = -ENOMEM;
goto exit_error;
}
memzero(info, sizeof(*info));
dev_set_drvdata(dev, info);
res = pdev->resource; /* assume that the flash has one resource */
info->map.phys = res->start;
info->map.size = res->end - res->start + 1;
info->map.name = dev->bus_id;
info->map.bankwidth = 2;
if (info->map.size > AREA_MAXSIZE)
info->map.size = AREA_MAXSIZE;
pr_debug("%s: area %08lx, size %ld\n", __FUNCTION__,
info->map.phys, info->map.size);
info->area = request_mem_region(res->start, info->map.size,
pdev->name);
if (info->area == NULL) {
printk(KERN_ERR PFX "cannot reserve flash memory region\n");
err = -ENOENT;
goto exit_error;
}
info->map.virt = ioremap(res->start, info->map.size);
pr_debug("%s: virt at %08x\n", __FUNCTION__, (int)info->map.virt);
if (info->map.virt == 0) {
printk(KERN_ERR PFX "failed to ioremap() region\n");
err = -EIO;
goto exit_error;
}
simple_map_init(&info->map);
/* enable the write to the flash area */
bast_flash_setrw(1);
/* probe for the device(s) */
info->mtd = do_map_probe("jedec_probe", &info->map);
if (info->mtd == NULL)
info->mtd = do_map_probe("cfi_probe", &info->map);
if (info->mtd == NULL) {
printk(KERN_ERR PFX "map_probe() failed\n");
err = -ENXIO;
goto exit_error;
}
/* mark ourselves as the owner */
info->mtd->owner = THIS_MODULE;
err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
if (err > 0) {
err = add_mtd_partitions(info->mtd, info->partitions, err);
if (err)
printk(KERN_ERR PFX "cannot add/parse partitions\n");
}
if (err == 0)
return 0;
/* fall through to exit error */
exit_error:
bast_flash_remove(dev);
return err;
}
static struct device_driver bast_flash_driver = {
.name = "bast-nor",
.bus = &platform_bus_type,
.probe = bast_flash_probe,
.remove = bast_flash_remove,
};
static int __init bast_flash_init(void)
{
printk("BAST NOR-Flash Driver, (c) 2004 Simtec Electronics\n");
return driver_register(&bast_flash_driver);
}
static void __exit bast_flash_exit(void)
{
driver_unregister(&bast_flash_driver);
}
module_init(bast_flash_init);
module_exit(bast_flash_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_DESCRIPTION("BAST MTD Map driver");

112
drivers/mtd/maps/beech-mtd.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,112 @@
/*
* $Id: beech-mtd.c,v 1.10 2004/11/04 13:24:14 gleixner Exp $
*
* drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for
* IBM 405LP Beech boards.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Copyright (C) 2002, International Business Machines Corporation
* All Rights Reserved.
*
* Bishop Brock
* IBM Research, Austin Center for Low-Power Computing
* bcbrock@us.ibm.com
* March 2002
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/ibm4xx.h>
#define NAME "Beech Linux Flash"
#define PADDR BEECH_BIGFLASH_PADDR
#define SIZE BEECH_BIGFLASH_SIZE
#define BUSWIDTH 1
/* Flash memories on these boards are memory resources, accessed big-endian. */
static struct map_info beech_mtd_map = {
.name = NAME,
.size = SIZE,
.bankwidth = BUSWIDTH,
.phys = PADDR
};
static struct mtd_info *beech_mtd;
static struct mtd_partition beech_partitions[2] = {
{
.name = "Linux Kernel",
.size = BEECH_KERNEL_SIZE,
.offset = BEECH_KERNEL_OFFSET
}, {
.name = "Free Area",
.size = BEECH_FREE_AREA_SIZE,
.offset = BEECH_FREE_AREA_OFFSET
}
};
static int __init
init_beech_mtd(void)
{
printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
beech_mtd_map.virt = ioremap(PADDR, SIZE);
if (!beech_mtd_map.virt) {
printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
return -EIO;
}
simple_map_init(&beech_mtd_map);
printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map);
if (!beech_mtd)
return -ENXIO;
beech_mtd->owner = THIS_MODULE;
return add_mtd_partitions(beech_mtd, beech_partitions, 2);
}
static void __exit
cleanup_beech_mtd(void)
{
if (beech_mtd) {
del_mtd_partitions(beech_mtd);
map_destroy(beech_mtd);
iounmap((void *) beech_mtd_map.virt);
}
}
module_init(init_beech_mtd);
module_exit(cleanup_beech_mtd);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bishop Brock <bcbrock@us.ibm.com>");
MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Beech boards");

268
drivers/mtd/maps/cdb89712.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,268 @@
/*
* Flash on Cirrus CDB89712
*
* $Id: cdb89712.c,v 1.10 2004/11/04 13:24:14 gleixner Exp $
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
static struct mtd_info *flash_mtd;
struct map_info cdb89712_flash_map = {
.name = "flash",
.size = FLASH_SIZE,
.bankwidth = FLASH_WIDTH,
.phys = FLASH_START,
};
struct resource cdb89712_flash_resource = {
.name = "Flash",
.start = FLASH_START,
.end = FLASH_START + FLASH_SIZE - 1,
.flags = IORESOURCE_IO | IORESOURCE_BUSY,
};
static int __init init_cdb89712_flash (void)
{
int err;
if (request_resource (&ioport_resource, &cdb89712_flash_resource)) {
printk(KERN_NOTICE "Failed to reserve Cdb89712 FLASH space\n");
err = -EBUSY;
goto out;
}
cdb89712_flash_map.virt = ioremap(FLASH_START, FLASH_SIZE);
if (!cdb89712_flash_map.virt) {
printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n");
err = -EIO;
goto out_resource;
}
simple_map_init(&cdb89712_flash_map);
flash_mtd = do_map_probe("cfi_probe", &cdb89712_flash_map);
if (!flash_mtd) {
flash_mtd = do_map_probe("map_rom", &cdb89712_flash_map);
if (flash_mtd)
flash_mtd->erasesize = 0x10000;
}
if (!flash_mtd) {
printk("FLASH probe failed\n");
err = -ENXIO;
goto out_ioremap;
}
flash_mtd->owner = THIS_MODULE;
if (add_mtd_device(flash_mtd)) {
printk("FLASH device addition failed\n");
err = -ENOMEM;
goto out_probe;
}
return 0;
out_probe:
map_destroy(flash_mtd);
flash_mtd = 0;
out_ioremap:
iounmap((void *)cdb89712_flash_map.virt);
out_resource:
release_resource (&cdb89712_flash_resource);
out:
return err;
}
static struct mtd_info *sram_mtd;
struct map_info cdb89712_sram_map = {
.name = "SRAM",
.size = SRAM_SIZE,
.bankwidth = SRAM_WIDTH,
.phys = SRAM_START,
};
struct resource cdb89712_sram_resource = {
.name = "SRAM",
.start = SRAM_START,
.end = SRAM_START + SRAM_SIZE - 1,
.flags = IORESOURCE_IO | IORESOURCE_BUSY,
};
static int __init init_cdb89712_sram (void)
{
int err;
if (request_resource (&ioport_resource, &cdb89712_sram_resource)) {
printk(KERN_NOTICE "Failed to reserve Cdb89712 SRAM space\n");
err = -EBUSY;
goto out;
}
cdb89712_sram_map.virt = ioremap(SRAM_START, SRAM_SIZE);
if (!cdb89712_sram_map.virt) {
printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n");
err = -EIO;
goto out_resource;
}
simple_map_init(&cdb89712_sram_map);
sram_mtd = do_map_probe("map_ram", &cdb89712_sram_map);
if (!sram_mtd) {
printk("SRAM probe failed\n");
err = -ENXIO;
goto out_ioremap;
}
sram_mtd->owner = THIS_MODULE;
sram_mtd->erasesize = 16;
if (add_mtd_device(sram_mtd)) {
printk("SRAM device addition failed\n");
err = -ENOMEM;
goto out_probe;
}
return 0;
out_probe:
map_destroy(sram_mtd);
sram_mtd = 0;
out_ioremap:
iounmap((void *)cdb89712_sram_map.virt);
out_resource:
release_resource (&cdb89712_sram_resource);
out:
return err;
}
static struct mtd_info *bootrom_mtd;
struct map_info cdb89712_bootrom_map = {
.name = "BootROM",
.size = BOOTROM_SIZE,
.bankwidth = BOOTROM_WIDTH,
.phys = BOOTROM_START,
};
struct resource cdb89712_bootrom_resource = {
.name = "BootROM",
.start = BOOTROM_START,
.end = BOOTROM_START + BOOTROM_SIZE - 1,
.flags = IORESOURCE_IO | IORESOURCE_BUSY,
};
static int __init init_cdb89712_bootrom (void)
{
int err;
if (request_resource (&ioport_resource, &cdb89712_bootrom_resource)) {
printk(KERN_NOTICE "Failed to reserve Cdb89712 BOOTROM space\n");
err = -EBUSY;
goto out;
}
cdb89712_bootrom_map.virt = ioremap(BOOTROM_START, BOOTROM_SIZE);
if (!cdb89712_bootrom_map.virt) {
printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n");
err = -EIO;
goto out_resource;
}
simple_map_init(&cdb89712_bootrom_map);
bootrom_mtd = do_map_probe("map_rom", &cdb89712_bootrom_map);
if (!bootrom_mtd) {
printk("BootROM probe failed\n");
err = -ENXIO;
goto out_ioremap;
}
bootrom_mtd->owner = THIS_MODULE;
bootrom_mtd->erasesize = 0x10000;
if (add_mtd_device(bootrom_mtd)) {
printk("BootROM device addition failed\n");
err = -ENOMEM;
goto out_probe;
}
return 0;
out_probe:
map_destroy(bootrom_mtd);
bootrom_mtd = 0;
out_ioremap:
iounmap((void *)cdb89712_bootrom_map.virt);
out_resource:
release_resource (&cdb89712_bootrom_resource);
out:
return err;
}
static int __init init_cdb89712_maps(void)
{
printk(KERN_INFO "Cirrus CDB89712 MTD mappings:\n Flash 0x%x at 0x%x\n SRAM 0x%x at 0x%x\n BootROM 0x%x at 0x%x\n",
FLASH_SIZE, FLASH_START, SRAM_SIZE, SRAM_START, BOOTROM_SIZE, BOOTROM_START);
init_cdb89712_flash();
init_cdb89712_sram();
init_cdb89712_bootrom();
return 0;
}
static void __exit cleanup_cdb89712_maps(void)
{
if (sram_mtd) {
del_mtd_device(sram_mtd);
map_destroy(sram_mtd);
iounmap((void *)cdb89712_sram_map.virt);
release_resource (&cdb89712_sram_resource);
}
if (flash_mtd) {
del_mtd_device(flash_mtd);
map_destroy(flash_mtd);
iounmap((void *)cdb89712_flash_map.virt);
release_resource (&cdb89712_flash_resource);
}
if (bootrom_mtd) {
del_mtd_device(bootrom_mtd);
map_destroy(bootrom_mtd);
iounmap((void *)cdb89712_bootrom_map.virt);
release_resource (&cdb89712_bootrom_resource);
}
}
module_init(init_cdb89712_maps);
module_exit(cleanup_cdb89712_maps);
MODULE_AUTHOR("Ray L");
MODULE_DESCRIPTION("ARM CDB89712 map driver");
MODULE_LICENSE("GPL");

350
drivers/mtd/maps/ceiva.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,350 @@
/*
* Ceiva flash memory driver.
* Copyright (C) 2002 Rob Scott <rscott@mtrob.fdns.net>
*
* Note: this driver supports jedec compatible devices. Modification
* for CFI compatible devices should be straight forward: change
* jedec_probe to cfi_probe.
*
* Based on: sa1100-flash.c, which has the following copyright:
* Flash memory access on SA11x0 based devices
*
* (C) 2000 Nicolas Pitre <nico@cam.org>
*
* $Id: ceiva.c,v 1.11 2004/09/16 23:27:12 gleixner Exp $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/concat.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/io.h>
#include <asm/sizes.h>
/*
* This isn't complete yet, so...
*/
#define CONFIG_MTD_CEIVA_STATICMAP
#ifdef CONFIG_MTD_CEIVA_STATICMAP
/*
* See include/linux/mtd/partitions.h for definition of the mtd_partition
* structure.
*
* Please note:
* 1. The flash size given should be the largest flash size that can
* be accomodated.
*
* 2. The bus width must defined in clps_setup_flash.
*
* The MTD layer will detect flash chip aliasing and reduce the size of
* the map accordingly.
*
*/
#ifdef CONFIG_ARCH_CEIVA
/* Flash / Partition sizing */
/* For the 28F8003, we use the block mapping to calcuate the sizes */
#define MAX_SIZE_KiB (16 + 8 + 8 + 96 + (7*128))
#define BOOT_PARTITION_SIZE_KiB (16)
#define PARAMS_PARTITION_SIZE_KiB (8)
#define KERNEL_PARTITION_SIZE_KiB (4*128)
/* Use both remaing portion of first flash, and all of second flash */
#define ROOT_PARTITION_SIZE_KiB (3*128) + (8*128)
static struct mtd_partition ceiva_partitions[] = {
{
.name = "Ceiva BOOT partition",
.size = BOOT_PARTITION_SIZE_KiB*1024,
.offset = 0,
},{
.name = "Ceiva parameters partition",
.size = PARAMS_PARTITION_SIZE_KiB*1024,
.offset = (16 + 8) * 1024,
},{
.name = "Ceiva kernel partition",
.size = (KERNEL_PARTITION_SIZE_KiB)*1024,
.offset = 0x20000,
},{
.name = "Ceiva root filesystem partition",
.offset = MTDPART_OFS_APPEND,
.size = (ROOT_PARTITION_SIZE_KiB)*1024,
}
};
#endif
static int __init clps_static_partitions(struct mtd_partition **parts)
{
int nb_parts = 0;
#ifdef CONFIG_ARCH_CEIVA
if (machine_is_ceiva()) {
*parts = ceiva_partitions;
nb_parts = ARRAY_SIZE(ceiva_partitions);
}
#endif
return nb_parts;
}
#endif
struct clps_info {
unsigned long base;
unsigned long size;
int width;
void *vbase;
struct map_info *map;
struct mtd_info *mtd;
struct resource *res;
};
#define NR_SUBMTD 4
static struct clps_info info[NR_SUBMTD];
static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info **rmtd)
{
struct mtd_info *subdev[nr];
struct map_info *maps;
int i, found = 0, ret = 0;
/*
* Allocate the map_info structs in one go.
*/
maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
if (!maps)
return -ENOMEM;
memset(maps, 0, sizeof(struct map_info) * nr);
/*
* Claim and then map the memory regions.
*/
for (i = 0; i < nr; i++) {
if (clps[i].base == (unsigned long)-1)
break;
clps[i].res = request_mem_region(clps[i].base, clps[i].size, "clps flash");
if (!clps[i].res) {
ret = -EBUSY;
break;
}
clps[i].map = maps + i;
clps[i].map->name = "clps flash";
clps[i].map->phys = clps[i].base;
clps[i].vbase = ioremap(clps[i].base, clps[i].size);
if (!clps[i].vbase) {
ret = -ENOMEM;
break;
}
clps[i].map->virt = (void __iomem *)clps[i].vbase;
clps[i].map->bankwidth = clps[i].width;
clps[i].map->size = clps[i].size;
simple_map_init(&clps[i].map);
clps[i].mtd = do_map_probe("jedec_probe", clps[i].map);
if (clps[i].mtd == NULL) {
ret = -ENXIO;
break;
}
clps[i].mtd->owner = THIS_MODULE;
subdev[i] = clps[i].mtd;
printk(KERN_INFO "clps flash: JEDEC device at 0x%08lx, %dMiB, "
"%d-bit\n", clps[i].base, clps[i].mtd->size >> 20,
clps[i].width * 8);
found += 1;
}
/*
* ENXIO is special. It means we didn't find a chip when
* we probed. We need to tear down the mapping, free the
* resource and mark it as such.
*/
if (ret == -ENXIO) {
iounmap(clps[i].vbase);
clps[i].vbase = NULL;
release_resource(clps[i].res);
clps[i].res = NULL;
}
/*
* If we found one device, don't bother with concat support.
* If we found multiple devices, use concat if we have it
* available, otherwise fail.
*/
if (ret == 0 || ret == -ENXIO) {
if (found == 1) {
*rmtd = subdev[0];
ret = 0;
} else if (found > 1) {
/*
* We detected multiple devices. Concatenate
* them together.
*/
#ifdef CONFIG_MTD_CONCAT
*rmtd = mtd_concat_create(subdev, found,
"clps flash");
if (*rmtd == NULL)
ret = -ENXIO;
#else
printk(KERN_ERR "clps flash: multiple devices "
"found but MTD concat support disabled.\n");
ret = -ENXIO;
#endif
}
}
/*
* If we failed, clean up.
*/
if (ret) {
do {
if (clps[i].mtd)
map_destroy(clps[i].mtd);
if (clps[i].vbase)
iounmap(clps[i].vbase);
if (clps[i].res)
release_resource(clps[i].res);
} while (i--);
kfree(maps);
}
return ret;
}
static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd)
{
int i;
del_mtd_partitions(mtd);
if (mtd != clps[0].mtd)
mtd_concat_destroy(mtd);
for (i = NR_SUBMTD; i >= 0; i--) {
if (clps[i].mtd)
map_destroy(clps[i].mtd);
if (clps[i].vbase)
iounmap(clps[i].vbase);
if (clps[i].res)
release_resource(clps[i].res);
}
kfree(clps[0].map);
}
/*
* We define the memory space, size, and width for the flash memory
* space here.
*/
static int __init clps_setup_flash(void)
{
int nr;
#ifdef CONFIG_ARCH_CEIVA
if (machine_is_ceiva()) {
info[0].base = CS0_PHYS_BASE;
info[0].size = SZ_32M;
info[0].width = CEIVA_FLASH_WIDTH;
info[1].base = CS1_PHYS_BASE;
info[1].size = SZ_32M;
info[1].width = CEIVA_FLASH_WIDTH;
nr = 2;
}
#endif
return nr;
}
static struct mtd_partition *parsed_parts;
static const char *probes[] = { "cmdlinepart", "RedBoot", NULL };
static void __init clps_locate_partitions(struct mtd_info *mtd)
{
const char *part_type = NULL;
int nr_parts = 0;
do {
/*
* Partition selection stuff.
*/
nr_parts = parse_mtd_partitions(mtd, probes, &parsed_parts, 0);
if (nr_parts > 0) {
part_type = "command line";
break;
}
#ifdef CONFIG_MTD_CEIVA_STATICMAP
nr_parts = clps_static_partitions(&parsed_parts);
if (nr_parts > 0) {
part_type = "static";
break;
}
printk("found: %d partitions\n", nr_parts);
#endif
} while (0);
if (nr_parts == 0) {
printk(KERN_NOTICE "clps flash: no partition info "
"available, registering whole flash\n");
add_mtd_device(mtd);
} else {
printk(KERN_NOTICE "clps flash: using %s partition "
"definition\n", part_type);
add_mtd_partitions(mtd, parsed_parts, nr_parts);
}
/* Always succeeds. */
}
static void __exit clps_destroy_partitions(void)
{
if (parsed_parts)
kfree(parsed_parts);
}
static struct mtd_info *mymtd;
static int __init clps_mtd_init(void)
{
int ret;
int nr;
nr = clps_setup_flash();
if (nr < 0)
return nr;
ret = clps_setup_mtd(info, nr, &mymtd);
if (ret)
return ret;
clps_locate_partitions(mymtd);
return 0;
}
static void __exit clps_mtd_cleanup(void)
{
clps_destroy_mtd(info, mymtd);
clps_destroy_partitions();
}
module_init(clps_mtd_init);
module_exit(clps_mtd_cleanup);
MODULE_AUTHOR("Rob Scott");
MODULE_DESCRIPTION("Cirrus Logic JEDEC map driver");
MODULE_LICENSE("GPL");

139
drivers/mtd/maps/cfi_flagadm.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,139 @@
/*
* Copyright <20> 2001 Flaga hf. Medical Devices, K<>ri Dav<61><76>sson <kd@flaga.is>
*
* $Id: cfi_flagadm.c,v 1.14 2004/11/04 13:24:14 gleixner Exp $
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
/* We split the flash chip up into four parts.
* 1: bootloader firts 128k (0x00000000 - 0x0001FFFF) size 0x020000
* 2: kernel 640k (0x00020000 - 0x000BFFFF) size 0x0A0000
* 3: compressed 1536k root ramdisk (0x000C0000 - 0x0023FFFF) size 0x180000
* 4: writeable diskpartition (jffs)(0x00240000 - 0x003FFFFF) size 0x1C0000
*/
#define FLASH_PHYS_ADDR 0x40000000
#define FLASH_SIZE 0x400000
#define FLASH_PARTITION0_ADDR 0x00000000
#define FLASH_PARTITION0_SIZE 0x00020000
#define FLASH_PARTITION1_ADDR 0x00020000
#define FLASH_PARTITION1_SIZE 0x000A0000
#define FLASH_PARTITION2_ADDR 0x000C0000
#define FLASH_PARTITION2_SIZE 0x00180000
#define FLASH_PARTITION3_ADDR 0x00240000
#define FLASH_PARTITION3_SIZE 0x001C0000
struct map_info flagadm_map = {
.name = "FlagaDM flash device",
.size = FLASH_SIZE,
.bankwidth = 2,
};
struct mtd_partition flagadm_parts[] = {
{
.name = "Bootloader",
.offset = FLASH_PARTITION0_ADDR,
.size = FLASH_PARTITION0_SIZE
},
{
.name = "Kernel image",
.offset = FLASH_PARTITION1_ADDR,
.size = FLASH_PARTITION1_SIZE
},
{
.name = "Initial ramdisk image",
.offset = FLASH_PARTITION2_ADDR,
.size = FLASH_PARTITION2_SIZE
},
{
.name = "Persistant storage",
.offset = FLASH_PARTITION3_ADDR,
.size = FLASH_PARTITION3_SIZE
}
};
#define PARTITION_COUNT (sizeof(flagadm_parts)/sizeof(struct mtd_partition))
static struct mtd_info *mymtd;
int __init init_flagadm(void)
{
printk(KERN_NOTICE "FlagaDM flash device: %x at %x\n",
FLASH_SIZE, FLASH_PHYS_ADDR);
flagadm_map.phys = FLASH_PHYS_ADDR;
flagadm_map.virt = ioremap(FLASH_PHYS_ADDR,
FLASH_SIZE);
if (!flagadm_map.virt) {
printk("Failed to ioremap\n");
return -EIO;
}
simple_map_init(&flagadm_map);
mymtd = do_map_probe("cfi_probe", &flagadm_map);
if (mymtd) {
mymtd->owner = THIS_MODULE;
add_mtd_partitions(mymtd, flagadm_parts, PARTITION_COUNT);
printk(KERN_NOTICE "FlagaDM flash device initialized\n");
return 0;
}
iounmap((void *)flagadm_map.virt);
return -ENXIO;
}
static void __exit cleanup_flagadm(void)
{
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
if (flagadm_map.virt) {
iounmap((void *)flagadm_map.virt);
flagadm_map.virt = 0;
}
}
module_init(init_flagadm);
module_exit(cleanup_flagadm);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("K<EFBFBD>ri Dav<61><76>sson <kd@flaga.is>");
MODULE_DESCRIPTION("MTD map driver for Flaga digital module");

270
drivers/mtd/maps/cstm_mips_ixx.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,270 @@
/*
* $Id: cstm_mips_ixx.c,v 1.12 2004/11/04 13:24:14 gleixner Exp $
*
* Mapping of a custom board with both AMD CFI and JEDEC flash in partitions.
* Config with both CFI and JEDEC device support.
*
* Basically physmap.c with the addition of partitions and
* an array of mapping info to accomodate more than one flash type per board.
*
* Copyright 2000 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/config.h>
#include <linux/delay.h>
#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
#define CC_GCR 0xB4013818
#define CC_GPBCR 0xB401380A
#define CC_GPBDR 0xB4013808
#define CC_M68K_DEVICE 1
#define CC_M68K_FUNCTION 6
#define CC_CONFADDR 0xB8004000
#define CC_CONFDATA 0xB8004004
#define CC_FC_FCR 0xB8002004
#define CC_FC_DCR 0xB8002008
#define CC_GPACR 0xB4013802
#define CC_GPAICR 0xB4013804
#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp)
{
static DEFINE_SPINLOCK(vpp_lock);
static int vpp_count = 0;
unsigned long flags;
spin_lock_irqsave(&vpp_lock, flags);
if (vpp) {
if (!vpp_count++) {
__u16 data;
__u8 data1;
static u8 first = 1;
// Set GPIO port B pin3 to high
data = *(__u16 *)(CC_GPBCR);
data = (data & 0xff0f) | 0x0040;
*(__u16 *)CC_GPBCR = data;
*(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) | 0x08;
if (first) {
first = 0;
/* need to have this delay for first
enabling vpp after powerup */
udelay(40);
}
}
} else {
if (!--vpp_count) {
__u16 data;
// Set GPIO port B pin3 to high
data = *(__u16 *)(CC_GPBCR);
data = (data & 0xff3f) | 0x0040;
*(__u16 *)CC_GPBCR = data;
*(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) & 0xf7;
}
}
spin_unlock_irqrestore(&vpp_lock, flags);
}
#endif
/* board and partition description */
#define MAX_PHYSMAP_PARTITIONS 8
struct cstm_mips_ixx_info {
char *name;
unsigned long window_addr;
unsigned long window_size;
int bankwidth;
int num_partitions;
};
#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type
const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] =
{
{ // 28F128J3A in 2x16 configuration
"big flash", // name
0x08000000, // window_addr
0x02000000, // window_size
4, // bankwidth
1, // num_partitions
}
};
static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = {
{ // 28F128J3A in 2x16 configuration
{
.name = "main partition ",
.size = 0x02000000, // 128 x 2 x 128k byte sectors
.offset = 0,
},
},
};
#else /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type
const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] =
{
{
"MTD flash", // name
CONFIG_MTD_CSTM_MIPS_IXX_START, // window_addr
CONFIG_MTD_CSTM_MIPS_IXX_LEN, // window_size
CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH, // bankwidth
1, // num_partitions
},
};
static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = {
{
{
.name = "main partition",
.size = CONFIG_MTD_CSTM_MIPS_IXX_LEN,
.offset = 0,
},
},
};
#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
struct map_info cstm_mips_ixx_map[PHYSMAP_NUMBER];
int __init init_cstm_mips_ixx(void)
{
int i;
int jedec;
struct mtd_info *mymtd;
struct mtd_partition *parts;
/* Initialize mapping */
for (i=0;i<PHYSMAP_NUMBER;i++) {
printk(KERN_NOTICE "cstm_mips_ixx flash device: 0x%lx at 0x%lx\n",
cstm_mips_ixx_board_desc[i].window_size, cstm_mips_ixx_board_desc[i].window_addr);
cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr;
cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size);
if (!cstm_mips_ixx_map[i].virt) {
printk(KERN_WARNING "Failed to ioremap\n");
return -EIO;
}
cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name;
cstm_mips_ixx_map[i].size = cstm_mips_ixx_board_desc[i].window_size;
cstm_mips_ixx_map[i].bankwidth = cstm_mips_ixx_board_desc[i].bankwidth;
#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
cstm_mips_ixx_map[i].set_vpp = cstm_mips_ixx_set_vpp;
#endif
simple_map_init(&cstm_mips_ixx_map[i]);
//printk(KERN_NOTICE "cstm_mips_ixx: ioremap is %x\n",(unsigned int)(cstm_mips_ixx_map[i].virt));
}
#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
setup_ITE_IVR_flash();
#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
for (i=0;i<PHYSMAP_NUMBER;i++) {
parts = &cstm_mips_ixx_partitions[i][0];
jedec = 0;
mymtd = (struct mtd_info *)do_map_probe("cfi_probe", &cstm_mips_ixx_map[i]);
//printk(KERN_NOTICE "phymap %d cfi_probe: mymtd is %x\n",i,(unsigned int)mymtd);
if (!mymtd) {
jedec = 1;
mymtd = (struct mtd_info *)do_map_probe("jedec", &cstm_mips_ixx_map[i]);
printk(KERN_NOTICE "cstm_mips_ixx %d jedec: mymtd is %x\n",i,(unsigned int)mymtd);
}
if (mymtd) {
mymtd->owner = THIS_MODULE;
cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd;
add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions);
}
else
return -ENXIO;
}
return 0;
}
static void __exit cleanup_cstm_mips_ixx(void)
{
int i;
struct mtd_info *mymtd;
for (i=0;i<PHYSMAP_NUMBER;i++) {
mymtd = (struct mtd_info *)cstm_mips_ixx_map[i].map_priv_2;
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
if (cstm_mips_ixx_map[i].virt) {
iounmap((void *)cstm_mips_ixx_map[i].virt);
cstm_mips_ixx_map[i].virt = 0;
}
}
}
#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
void PCISetULongByOffset(__u32 DevNumber, __u32 FuncNumber, __u32 Offset, __u32 data)
{
__u32 offset;
offset = ( unsigned long )( 0x80000000 | ( DevNumber << 11 ) + ( FuncNumber << 8 ) + Offset) ;
*(__u32 *)CC_CONFADDR = offset;
*(__u32 *)CC_CONFDATA = data;
}
void setup_ITE_IVR_flash()
{
__u32 size, base;
size = 0x0e000000; // 32MiB
base = (0x08000000) >> 8 >>1; // Bug: we must shift one more bit
/* need to set ITE flash to 32 bits instead of default 8 */
#ifdef CONFIG_MIPS_IVR
*(__u32 *)CC_FC_FCR = 0x55;
*(__u32 *)CC_GPACR = 0xfffc;
#else
*(__u32 *)CC_FC_FCR = 0x77;
#endif
/* turn bursting off */
*(__u32 *)CC_FC_DCR = 0x0;
/* setup for one chip 4 byte PCI access */
PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x60, size | base);
PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x64, 0x02);
}
#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
module_init(init_cstm_mips_ixx);
module_exit(cleanup_cstm_mips_ixx);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
MODULE_DESCRIPTION("MTD map driver for ITE 8172G and Globespan IVR boards");

187
drivers/mtd/maps/db1550-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,187 @@
/*
* Flash memory access on Alchemy Db1550 board
*
* $Id: db1550-flash.c,v 1.7 2004/11/04 13:24:14 gleixner Exp $
*
* (C) 2004 Embedded Edge, LLC, based on db1550-flash.c:
* (C) 2003, 2004 Pete Popov <ppopov@embeddedalley.com>
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#ifdef DEBUG_RW
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
static unsigned long window_addr;
static unsigned long window_size;
static struct map_info db1550_map = {
.name = "Db1550 flash",
};
static unsigned char flash_bankwidth = 4;
/*
* Support only 64MB NOR Flash parts
*/
#if defined(CONFIG_MTD_DB1550_BOOT) && defined(CONFIG_MTD_DB1550_USER)
#define DB1550_BOTH_BANKS
#elif defined(CONFIG_MTD_DB1550_BOOT) && !defined(CONFIG_MTD_DB1550_USER)
#define DB1550_BOOT_ONLY
#elif !defined(CONFIG_MTD_DB1550_BOOT) && defined(CONFIG_MTD_DB1550_USER)
#define DB1550_USER_ONLY
#endif
#ifdef DB1550_BOTH_BANKS
/* both banks will be used. Combine the first bank and the first
* part of the second bank together into a single jffs/jffs2
* partition.
*/
static struct mtd_partition db1550_partitions[] = {
/* assume boot[2:0]:swap is '0000' or '1000', which translates to:
* 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
* 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
*/
{
.name = "User FS",
.size = (0x1FC00000 - 0x18000000),
.offset = 0x0000000
},{
.name = "yamon",
.size = 0x0100000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE
},{
.name = "raw kernel",
.size = (0x300000 - 0x40000), /* last 256KB is yamon env */
.offset = MTDPART_OFS_APPEND,
}
};
#elif defined(DB1550_BOOT_ONLY)
static struct mtd_partition db1550_partitions[] = {
/* assume boot[2:0]:swap is '0000' or '1000', which translates to:
* 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
*/
{
.name = "User FS",
.size = 0x03c00000,
.offset = 0x0000000
},{
.name = "yamon",
.size = 0x0100000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE
},{
.name = "raw kernel",
.size = (0x300000-0x40000), /* last 256KB is yamon env */
.offset = MTDPART_OFS_APPEND,
}
};
#elif defined(DB1550_USER_ONLY)
static struct mtd_partition db1550_partitions[] = {
/* assume boot[2:0]:swap is '0000' or '1000', which translates to:
* 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
*/
{
.name = "User FS",
.size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */
.offset = 0x0000000
},{
.name = "raw kernel",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND,
}
};
#else
#error MTD_DB1550 define combo error /* should never happen */
#endif
#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
static struct mtd_info *mymtd;
/*
* Probe the flash density and setup window address and size
* based on user CONFIG options. There are times when we don't
* want the MTD driver to be probing the boot or user flash,
* so having the option to enable only one bank is important.
*/
int setup_flash_params(void)
{
#if defined(DB1550_BOTH_BANKS)
window_addr = 0x18000000;
window_size = 0x8000000;
#elif defined(DB1550_BOOT_ONLY)
window_addr = 0x1C000000;
window_size = 0x4000000;
#else /* USER ONLY */
window_addr = 0x18000000;
window_size = 0x4000000;
#endif
return 0;
}
int __init db1550_mtd_init(void)
{
struct mtd_partition *parts;
int nb_parts = 0;
/* Default flash bankwidth */
db1550_map.bankwidth = flash_bankwidth;
if (setup_flash_params())
return -ENXIO;
/*
* Static partition definition selection
*/
parts = db1550_partitions;
nb_parts = NB_OF(db1550_partitions);
db1550_map.size = window_size;
/*
* Now let's probe for the actual flash. Do it here since
* specific machine settings might have been set above.
*/
printk(KERN_NOTICE "Db1550 flash: probing %d-bit flash bus\n",
db1550_map.bankwidth*8);
db1550_map.virt = ioremap(window_addr, window_size);
mymtd = do_map_probe("cfi_probe", &db1550_map);
if (!mymtd) return -ENXIO;
mymtd->owner = THIS_MODULE;
add_mtd_partitions(mymtd, parts, nb_parts);
return 0;
}
static void __exit db1550_mtd_cleanup(void)
{
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
iounmap((void *) db1550_map.virt);
}
}
module_init(db1550_mtd_init);
module_exit(db1550_mtd_cleanup);
MODULE_AUTHOR("Embedded Edge, LLC");
MODULE_DESCRIPTION("Db1550 mtd map driver");
MODULE_LICENSE("GPL");

226
drivers/mtd/maps/db1x00-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,226 @@
/*
* Flash memory access on Alchemy Db1xxx boards
*
* $Id: db1x00-flash.c,v 1.6 2004/11/04 13:24:14 gleixner Exp $
*
* (C) 2003 Pete Popov <ppopov@embeddedalley.com>
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#ifdef DEBUG_RW
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
/* MTD CONFIG OPTIONS */
#if defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)
#define DB1X00_BOTH_BANKS
#elif defined(CONFIG_MTD_DB1X00_BOOT) && !defined(CONFIG_MTD_DB1X00_USER)
#define DB1X00_BOOT_ONLY
#elif !defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)
#define DB1X00_USER_ONLY
#endif
static unsigned long window_addr;
static unsigned long window_size;
static unsigned long flash_size;
static unsigned short *bcsr = (unsigned short *)0xAE000000;
static unsigned char flash_bankwidth = 4;
/*
* The Db1x boards support different flash densities. We setup
* the mtd_partition structures below for default of 64Mbit
* flash densities, and override the partitions sizes, if
* necessary, after we check the board status register.
*/
#ifdef DB1X00_BOTH_BANKS
/* both banks will be used. Combine the first bank and the first
* part of the second bank together into a single jffs/jffs2
* partition.
*/
static struct mtd_partition db1x00_partitions[] = {
{
.name = "User FS",
.size = 0x1c00000,
.offset = 0x0000000
},{
.name = "yamon",
.size = 0x0100000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE
},{
.name = "raw kernel",
.size = (0x300000-0x40000), /* last 256KB is env */
.offset = MTDPART_OFS_APPEND,
}
};
#elif defined(DB1X00_BOOT_ONLY)
static struct mtd_partition db1x00_partitions[] = {
{
.name = "User FS",
.size = 0x00c00000,
.offset = 0x0000000
},{
.name = "yamon",
.size = 0x0100000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE
},{
.name = "raw kernel",
.size = (0x300000-0x40000), /* last 256KB is env */
.offset = MTDPART_OFS_APPEND,
}
};
#elif defined(DB1X00_USER_ONLY)
static struct mtd_partition db1x00_partitions[] = {
{
.name = "User FS",
.size = 0x0e00000,
.offset = 0x0000000
},{
.name = "raw kernel",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND,
}
};
#else
#error MTD_DB1X00 define combo error /* should never happen */
#endif
#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
#define NAME "Db1x00 Linux Flash"
static struct map_info db1xxx_mtd_map = {
.name = NAME,
};
static struct mtd_partition *parsed_parts;
static struct mtd_info *db1xxx_mtd;
/*
* Probe the flash density and setup window address and size
* based on user CONFIG options. There are times when we don't
* want the MTD driver to be probing the boot or user flash,
* so having the option to enable only one bank is important.
*/
int setup_flash_params(void)
{
switch ((bcsr[2] >> 14) & 0x3) {
case 0: /* 64Mbit devices */
flash_size = 0x800000; /* 8MB per part */
#if defined(DB1X00_BOTH_BANKS)
window_addr = 0x1E000000;
window_size = 0x2000000;
#elif defined(DB1X00_BOOT_ONLY)
window_addr = 0x1F000000;
window_size = 0x1000000;
#else /* USER ONLY */
window_addr = 0x1E000000;
window_size = 0x1000000;
#endif
break;
case 1:
/* 128 Mbit devices */
flash_size = 0x1000000; /* 16MB per part */
#if defined(DB1X00_BOTH_BANKS)
window_addr = 0x1C000000;
window_size = 0x4000000;
/* USERFS from 0x1C00 0000 to 0x1FC0 0000 */
db1x00_partitions[0].size = 0x3C00000;
#elif defined(DB1X00_BOOT_ONLY)
window_addr = 0x1E000000;
window_size = 0x2000000;
/* USERFS from 0x1E00 0000 to 0x1FC0 0000 */
db1x00_partitions[0].size = 0x1C00000;
#else /* USER ONLY */
window_addr = 0x1C000000;
window_size = 0x2000000;
/* USERFS from 0x1C00 0000 to 0x1DE00000 */
db1x00_partitions[0].size = 0x1DE0000;
#endif
break;
case 2:
/* 256 Mbit devices */
flash_size = 0x4000000; /* 64MB per part */
#if defined(DB1X00_BOTH_BANKS)
return 1;
#elif defined(DB1X00_BOOT_ONLY)
/* Boot ROM flash bank only; no user bank */
window_addr = 0x1C000000;
window_size = 0x4000000;
/* USERFS from 0x1C00 0000 to 0x1FC00000 */
db1x00_partitions[0].size = 0x3C00000;
#else /* USER ONLY */
return 1;
#endif
break;
default:
return 1;
}
db1xxx_mtd_map.size = window_size;
db1xxx_mtd_map.bankwidth = flash_bankwidth;
db1xxx_mtd_map.phys = window_addr;
db1xxx_mtd_map.bankwidth = flash_bankwidth;
return 0;
}
int __init db1x00_mtd_init(void)
{
struct mtd_partition *parts;
int nb_parts = 0;
if (setup_flash_params())
return -ENXIO;
/*
* Static partition definition selection
*/
parts = db1x00_partitions;
nb_parts = NB_OF(db1x00_partitions);
/*
* Now let's probe for the actual flash. Do it here since
* specific machine settings might have been set above.
*/
printk(KERN_NOTICE "Db1xxx flash: probing %d-bit flash bus\n",
db1xxx_mtd_map.bankwidth*8);
db1xxx_mtd_map.virt = ioremap(window_addr, window_size);
db1xxx_mtd = do_map_probe("cfi_probe", &db1xxx_mtd_map);
if (!db1xxx_mtd) return -ENXIO;
db1xxx_mtd->owner = THIS_MODULE;
add_mtd_partitions(db1xxx_mtd, parts, nb_parts);
return 0;
}
static void __exit db1x00_mtd_cleanup(void)
{
if (db1xxx_mtd) {
del_mtd_partitions(db1xxx_mtd);
map_destroy(db1xxx_mtd);
if (parsed_parts)
kfree(parsed_parts);
}
}
module_init(db1x00_mtd_init);
module_exit(db1x00_mtd_cleanup);
MODULE_AUTHOR("Pete Popov");
MODULE_DESCRIPTION("Db1x00 mtd map driver");
MODULE_LICENSE("GPL");

126
drivers/mtd/maps/dbox2-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,126 @@
/*
* $Id: dbox2-flash.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $
*
* D-Box 2 flash driver
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/config.h>
#include <linux/errno.h>
/* partition_info gives details on the logical partitions that the split the
* single flash device into. If the size if zero we use up to the end of the
* device. */
static struct mtd_partition partition_info[]= {
{
.name = "BR bootloader",
.size = 128 * 1024,
.offset = 0,
.mask_flags = MTD_WRITEABLE
},
{
.name = "FLFS (U-Boot)",
.size = 128 * 1024,
.offset = MTDPART_OFS_APPEND,
.mask_flags = 0
},
{
.name = "Root (SquashFS)",
.size = 7040 * 1024,
.offset = MTDPART_OFS_APPEND,
.mask_flags = 0
},
{
.name = "var (JFFS2)",
.size = 896 * 1024,
.offset = MTDPART_OFS_APPEND,
.mask_flags = 0
},
{
.name = "Flash without bootloader",
.size = MTDPART_SIZ_FULL,
.offset = 128 * 1024,
.mask_flags = 0
},
{
.name = "Complete Flash",
.size = MTDPART_SIZ_FULL,
.offset = 0,
.mask_flags = MTD_WRITEABLE
}
};
#define NUM_PARTITIONS (sizeof(partition_info) / sizeof(partition_info[0]))
#define WINDOW_ADDR 0x10000000
#define WINDOW_SIZE 0x800000
static struct mtd_info *mymtd;
struct map_info dbox2_flash_map = {
.name = "D-Box 2 flash memory",
.size = WINDOW_SIZE,
.bankwidth = 4,
.phys = WINDOW_ADDR,
};
int __init init_dbox2_flash(void)
{
printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR);
dbox2_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!dbox2_flash_map.virt) {
printk("Failed to ioremap\n");
return -EIO;
}
simple_map_init(&dbox2_flash_map);
// Probe for dual Intel 28F320 or dual AMD
mymtd = do_map_probe("cfi_probe", &dbox2_flash_map);
if (!mymtd) {
// Probe for single Intel 28F640
dbox2_flash_map.bankwidth = 2;
mymtd = do_map_probe("cfi_probe", &dbox2_flash_map);
}
if (mymtd) {
mymtd->owner = THIS_MODULE;
/* Create MTD devices for each partition. */
add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
return 0;
}
iounmap((void *)dbox2_flash_map.virt);
return -ENXIO;
}
static void __exit cleanup_dbox2_flash(void)
{
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
if (dbox2_flash_map.virt) {
iounmap((void *)dbox2_flash_map.virt);
dbox2_flash_map.virt = 0;
}
}
module_init(init_dbox2_flash);
module_exit(cleanup_dbox2_flash);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("K<EFBFBD>ri Dav<61><76>sson <kd@flaga.is>, Bastian Blank <waldi@tuxbox.org>, Alexander Wild <wild@te-elektronik.com>");
MODULE_DESCRIPTION("MTD map driver for D-Box 2 board");

253
drivers/mtd/maps/dc21285.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,253 @@
/*
* MTD map driver for flash on the DC21285 (the StrongARM-110 companion chip)
*
* (C) 2000 Nicolas Pitre <nico@cam.org>
*
* This code is GPL
*
* $Id: dc21285.c,v 1.22 2004/11/01 13:39:21 rmk Exp $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach-types.h>
static struct mtd_info *dc21285_mtd;
#ifdef CONFIG_ARCH_NETWINDER
/*
* This is really ugly, but it seams to be the only
* realiable way to do it, as the cpld state machine
* is unpredictible. So we have a 25us penalty per
* write access.
*/
static void nw_en_write(void)
{
extern spinlock_t gpio_lock;
unsigned long flags;
/*
* we want to write a bit pattern XXX1 to Xilinx to enable
* the write gate, which will be open for about the next 2ms.
*/
spin_lock_irqsave(&gpio_lock, flags);
cpld_modify(1, 1);
spin_unlock_irqrestore(&gpio_lock, flags);
/*
* let the ISA bus to catch on...
*/
udelay(25);
}
#else
#define nw_en_write() do { } while (0)
#endif
static map_word dc21285_read8(struct map_info *map, unsigned long ofs)
{
map_word val;
val.x[0] = *(uint8_t*)(map->virt + ofs);
return val;
}
static map_word dc21285_read16(struct map_info *map, unsigned long ofs)
{
map_word val;
val.x[0] = *(uint16_t*)(map->virt + ofs);
return val;
}
static map_word dc21285_read32(struct map_info *map, unsigned long ofs)
{
map_word val;
val.x[0] = *(uint32_t*)(map->virt + ofs);
return val;
}
static void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
memcpy(to, (void*)(map->virt + from), len);
}
static void dc21285_write8(struct map_info *map, const map_word d, unsigned long adr)
{
if (machine_is_netwinder())
nw_en_write();
*CSR_ROMWRITEREG = adr & 3;
adr &= ~3;
*(uint8_t*)(map->virt + adr) = d.x[0];
}
static void dc21285_write16(struct map_info *map, const map_word d, unsigned long adr)
{
if (machine_is_netwinder())
nw_en_write();
*CSR_ROMWRITEREG = adr & 3;
adr &= ~3;
*(uint16_t*)(map->virt + adr) = d.x[0];
}
static void dc21285_write32(struct map_info *map, const map_word d, unsigned long adr)
{
if (machine_is_netwinder())
nw_en_write();
*(uint32_t*)(map->virt + adr) = d.x[0];
}
static void dc21285_copy_to_32(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
while (len > 0) {
map_word d;
d.x[0] = *((uint32_t*)from)++;
dc21285_write32(map, d, to);
to += 4;
len -= 4;
}
}
static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
while (len > 0) {
map_word d;
d.x[0] = *((uint16_t*)from)++;
dc21285_write16(map, d, to);
to += 2;
len -= 2;
}
}
static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
map_word d;
d.x[0] = *((uint8_t*)from)++;
dc21285_write8(map, d, to);
to++;
len--;
}
static struct map_info dc21285_map = {
.name = "DC21285 flash",
.phys = NO_XIP,
.size = 16*1024*1024,
.copy_from = dc21285_copy_from,
};
/* Partition stuff */
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition *dc21285_parts;
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
#endif
static int __init init_dc21285(void)
{
#ifdef CONFIG_MTD_PARTITIONS
int nrparts;
#endif
/* Determine bankwidth */
switch (*CSR_SA110_CNTL & (3<<14)) {
case SA110_CNTL_ROMWIDTH_8:
dc21285_map.bankwidth = 1;
dc21285_map.read = dc21285_read8;
dc21285_map.write = dc21285_write8;
dc21285_map.copy_to = dc21285_copy_to_8;
break;
case SA110_CNTL_ROMWIDTH_16:
dc21285_map.bankwidth = 2;
dc21285_map.read = dc21285_read16;
dc21285_map.write = dc21285_write16;
dc21285_map.copy_to = dc21285_copy_to_16;
break;
case SA110_CNTL_ROMWIDTH_32:
dc21285_map.bankwidth = 4;
dc21285_map.read = dc21285_read32;
dc21285_map.write = dc21285_write32;
dc21285_map.copy_to = dc21285_copy_to_32;
break;
default:
printk (KERN_ERR "DC21285 flash: undefined bankwidth\n");
return -ENXIO;
}
printk (KERN_NOTICE "DC21285 flash support (%d-bit bankwidth)\n",
dc21285_map.bankwidth*8);
/* Let's map the flash area */
dc21285_map.virt = ioremap(DC21285_FLASH, 16*1024*1024);
if (!dc21285_map.virt) {
printk("Failed to ioremap\n");
return -EIO;
}
if (machine_is_ebsa285()) {
dc21285_mtd = do_map_probe("cfi_probe", &dc21285_map);
} else {
dc21285_mtd = do_map_probe("jedec_probe", &dc21285_map);
}
if (!dc21285_mtd) {
iounmap(dc21285_map.virt);
return -ENXIO;
}
dc21285_mtd->owner = THIS_MODULE;
#ifdef CONFIG_MTD_PARTITIONS
nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0);
if (nrparts > 0)
add_mtd_partitions(dc21285_mtd, dc21285_parts, nrparts);
else
#endif
add_mtd_device(dc21285_mtd);
if(machine_is_ebsa285()) {
/*
* Flash timing is determined with bits 19-16 of the
* CSR_SA110_CNTL. The value is the number of wait cycles, or
* 0 for 16 cycles (the default). Cycles are 20 ns.
* Here we use 7 for 140 ns flash chips.
*/
/* access time */
*CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16));
/* burst time */
*CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20));
/* tristate time */
*CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24));
}
return 0;
}
static void __exit cleanup_dc21285(void)
{
#ifdef CONFIG_MTD_PARTITIONS
if (dc21285_parts) {
del_mtd_partitions(dc21285_mtd);
kfree(dc21285_parts);
} else
#endif
del_mtd_device(dc21285_mtd);
map_destroy(dc21285_mtd);
iounmap(dc21285_map.virt);
}
module_init(init_dc21285);
module_exit(cleanup_dc21285);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
MODULE_DESCRIPTION("MTD map driver for DC21285 boards");

495
drivers/mtd/maps/dilnetpc.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,495 @@
/* dilnetpc.c -- MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP"
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* $Id: dilnetpc.c,v 1.17 2004/11/28 09:40:39 dwmw2 Exp $
*
* The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems
* featuring the AMD Elan SC410 processor. There are two variants of this
* board: DNP/1486 and ADNP/1486. The DNP version has 2 megs of flash
* ROM (Intel 28F016S3) and 8 megs of DRAM, the ADNP version has 4 megs
* flash and 16 megs of RAM.
* For details, see http://www.ssv-embedded.de/ssv/pc104/p169.htm
* and http://www.ssv-embedded.de/ssv/pc104/p170.htm
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/concat.h>
/*
** The DIL/NetPC keeps its BIOS in two distinct flash blocks.
** Destroying any of these blocks transforms the DNPC into
** a paperweight (albeit not a very useful one, considering
** it only weighs a few grams).
**
** Therefore, the BIOS blocks must never be erased or written to
** except by people who know exactly what they are doing (e.g.
** to install a BIOS update). These partitions are marked read-only
** by default, but can be made read/write by undefining
** DNPC_BIOS_BLOCKS_WRITEPROTECTED:
*/
#define DNPC_BIOS_BLOCKS_WRITEPROTECTED
/*
** The ID string (in ROM) is checked to determine whether we
** are running on a DNP/1486 or ADNP/1486
*/
#define BIOSID_BASE 0x000fe100
#define ID_DNPC "DNP1486"
#define ID_ADNP "ADNP1486"
/*
** Address where the flash should appear in CPU space
*/
#define FLASH_BASE 0x2000000
/*
** Chip Setup and Control (CSC) indexed register space
*/
#define CSC_INDEX 0x22
#define CSC_DATA 0x23
#define CSC_MMSWAR 0x30 /* MMS window C-F attributes register */
#define CSC_MMSWDSR 0x31 /* MMS window C-F device select register */
#define CSC_RBWR 0xa7 /* GPIO Read-Back/Write Register B */
#define CSC_CR 0xd0 /* internal I/O device disable/Echo */
/* Z-bus/configuration register */
#define CSC_PCCMDCR 0xf1 /* PC card mode and DMA control register */
/*
** PC Card indexed register space:
*/
#define PCC_INDEX 0x3e0
#define PCC_DATA 0x3e1
#define PCC_AWER_B 0x46 /* Socket B Address Window enable register */
#define PCC_MWSAR_1_Lo 0x58 /* memory window 1 start address low register */
#define PCC_MWSAR_1_Hi 0x59 /* memory window 1 start address high register */
#define PCC_MWEAR_1_Lo 0x5A /* memory window 1 stop address low register */
#define PCC_MWEAR_1_Hi 0x5B /* memory window 1 stop address high register */
#define PCC_MWAOR_1_Lo 0x5C /* memory window 1 address offset low register */
#define PCC_MWAOR_1_Hi 0x5D /* memory window 1 address offset high register */
/*
** Access to SC4x0's Chip Setup and Control (CSC)
** and PC Card (PCC) indexed registers:
*/
static inline void setcsc(int reg, unsigned char data)
{
outb(reg, CSC_INDEX);
outb(data, CSC_DATA);
}
static inline unsigned char getcsc(int reg)
{
outb(reg, CSC_INDEX);
return(inb(CSC_DATA));
}
static inline void setpcc(int reg, unsigned char data)
{
outb(reg, PCC_INDEX);
outb(data, PCC_DATA);
}
static inline unsigned char getpcc(int reg)
{
outb(reg, PCC_INDEX);
return(inb(PCC_DATA));
}
/*
************************************************************
** Enable access to DIL/NetPC's flash by mapping it into
** the SC4x0's MMS Window C.
************************************************************
*/
static void dnpc_map_flash(unsigned long flash_base, unsigned long flash_size)
{
unsigned long flash_end = flash_base + flash_size - 1;
/*
** enable setup of MMS windows C-F:
*/
/* - enable PC Card indexed register space */
setcsc(CSC_CR, getcsc(CSC_CR) | 0x2);
/* - set PC Card controller to operate in standard mode */
setcsc(CSC_PCCMDCR, getcsc(CSC_PCCMDCR) & ~1);
/*
** Program base address and end address of window
** where the flash ROM should appear in CPU address space
*/
setpcc(PCC_MWSAR_1_Lo, (flash_base >> 12) & 0xff);
setpcc(PCC_MWSAR_1_Hi, (flash_base >> 20) & 0x3f);
setpcc(PCC_MWEAR_1_Lo, (flash_end >> 12) & 0xff);
setpcc(PCC_MWEAR_1_Hi, (flash_end >> 20) & 0x3f);
/* program offset of first flash location to appear in this window (0) */
setpcc(PCC_MWAOR_1_Lo, ((0 - flash_base) >> 12) & 0xff);
setpcc(PCC_MWAOR_1_Hi, ((0 - flash_base)>> 20) & 0x3f);
/* set attributes for MMS window C: non-cacheable, write-enabled */
setcsc(CSC_MMSWAR, getcsc(CSC_MMSWAR) & ~0x11);
/* select physical device ROMCS0 (i.e. flash) for MMS Window C */
setcsc(CSC_MMSWDSR, getcsc(CSC_MMSWDSR) & ~0x03);
/* enable memory window 1 */
setpcc(PCC_AWER_B, getpcc(PCC_AWER_B) | 0x02);
/* now disable PC Card indexed register space again */
setcsc(CSC_CR, getcsc(CSC_CR) & ~0x2);
}
/*
************************************************************
** Disable access to DIL/NetPC's flash by mapping it into
** the SC4x0's MMS Window C.
************************************************************
*/
static void dnpc_unmap_flash(void)
{
/* - enable PC Card indexed register space */
setcsc(CSC_CR, getcsc(CSC_CR) | 0x2);
/* disable memory window 1 */
setpcc(PCC_AWER_B, getpcc(PCC_AWER_B) & ~0x02);
/* now disable PC Card indexed register space again */
setcsc(CSC_CR, getcsc(CSC_CR) & ~0x2);
}
/*
************************************************************
** Enable/Disable VPP to write to flash
************************************************************
*/
static DEFINE_SPINLOCK(dnpc_spin);
static int vpp_counter = 0;
/*
** This is what has to be done for the DNP board ..
*/
static void dnp_set_vpp(struct map_info *not_used, int on)
{
spin_lock_irq(&dnpc_spin);
if (on)
{
if(++vpp_counter == 1)
setcsc(CSC_RBWR, getcsc(CSC_RBWR) & ~0x4);
}
else
{
if(--vpp_counter == 0)
setcsc(CSC_RBWR, getcsc(CSC_RBWR) | 0x4);
else if(vpp_counter < 0)
BUG();
}
spin_unlock_irq(&dnpc_spin);
}
/*
** .. and this the ADNP version:
*/
static void adnp_set_vpp(struct map_info *not_used, int on)
{
spin_lock_irq(&dnpc_spin);
if (on)
{
if(++vpp_counter == 1)
setcsc(CSC_RBWR, getcsc(CSC_RBWR) & ~0x8);
}
else
{
if(--vpp_counter == 0)
setcsc(CSC_RBWR, getcsc(CSC_RBWR) | 0x8);
else if(vpp_counter < 0)
BUG();
}
spin_unlock_irq(&dnpc_spin);
}
#define DNP_WINDOW_SIZE 0x00200000 /* DNP flash size is 2MiB */
#define ADNP_WINDOW_SIZE 0x00400000 /* ADNP flash size is 4MiB */
#define WINDOW_ADDR FLASH_BASE
static struct map_info dnpc_map = {
.name = "ADNP Flash Bank",
.size = ADNP_WINDOW_SIZE,
.bankwidth = 1,
.set_vpp = adnp_set_vpp,
.phys = WINDOW_ADDR
};
/*
** The layout of the flash is somewhat "strange":
**
** 1. 960 KiB (15 blocks) : Space for ROM Bootloader and user data
** 2. 64 KiB (1 block) : System BIOS
** 3. 960 KiB (15 blocks) : User Data (DNP model) or
** 3. 3008 KiB (47 blocks) : User Data (ADNP model)
** 4. 64 KiB (1 block) : System BIOS Entry
*/
static struct mtd_partition partition_info[]=
{
{
.name = "ADNP boot",
.offset = 0,
.size = 0xf0000,
},
{
.name = "ADNP system BIOS",
.offset = MTDPART_OFS_NXTBLK,
.size = 0x10000,
#ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED
.mask_flags = MTD_WRITEABLE,
#endif
},
{
.name = "ADNP file system",
.offset = MTDPART_OFS_NXTBLK,
.size = 0x2f0000,
},
{
.name = "ADNP system BIOS entry",
.offset = MTDPART_OFS_NXTBLK,
.size = MTDPART_SIZ_FULL,
#ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED
.mask_flags = MTD_WRITEABLE,
#endif
},
};
#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
static struct mtd_info *mymtd;
static struct mtd_info *lowlvl_parts[NUM_PARTITIONS];
static struct mtd_info *merged_mtd;
/*
** "Highlevel" partition info:
**
** Using the MTD concat layer, we can re-arrange partitions to our
** liking: we construct a virtual MTD device by concatenating the
** partitions, specifying the sequence such that the boot block
** is immediately followed by the filesystem block (i.e. the stupid
** system BIOS block is mapped to a different place). When re-partitioning
** this concatenated MTD device, we can set the boot block size to
** an arbitrary (though erase block aligned) value i.e. not one that
** is dictated by the flash's physical layout. We can thus set the
** boot block to be e.g. 64 KB (which is fully sufficient if we want
** to boot an etherboot image) or to -say- 1.5 MB if we want to boot
** a large kernel image. In all cases, the remainder of the flash
** is available as file system space.
*/
static struct mtd_partition higlvl_partition_info[]=
{
{
.name = "ADNP boot block",
.offset = 0,
.size = CONFIG_MTD_DILNETPC_BOOTSIZE,
},
{
.name = "ADNP file system space",
.offset = MTDPART_OFS_NXTBLK,
.size = ADNP_WINDOW_SIZE-CONFIG_MTD_DILNETPC_BOOTSIZE-0x20000,
},
{
.name = "ADNP system BIOS + BIOS Entry",
.offset = MTDPART_OFS_NXTBLK,
.size = MTDPART_SIZ_FULL,
#ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED
.mask_flags = MTD_WRITEABLE,
#endif
},
};
#define NUM_HIGHLVL_PARTITIONS (sizeof(higlvl_partition_info)/sizeof(partition_info[0]))
static int dnp_adnp_probe(void)
{
char *biosid, rc = -1;
biosid = (char*)ioremap(BIOSID_BASE, 16);
if(biosid)
{
if(!strcmp(biosid, ID_DNPC))
rc = 1; /* this is a DNPC */
else if(!strcmp(biosid, ID_ADNP))
rc = 0; /* this is a ADNPC */
}
iounmap((void *)biosid);
return(rc);
}
static int __init init_dnpc(void)
{
int is_dnp;
/*
** determine hardware (DNP/ADNP/invalid)
*/
if((is_dnp = dnp_adnp_probe()) < 0)
return -ENXIO;
/*
** Things are set up for ADNP by default
** -> modify all that needs to be different for DNP
*/
if(is_dnp)
{ /*
** Adjust window size, select correct set_vpp function.
** The partitioning scheme is identical on both DNP
** and ADNP except for the size of the third partition.
*/
int i;
dnpc_map.size = DNP_WINDOW_SIZE;
dnpc_map.set_vpp = dnp_set_vpp;
partition_info[2].size = 0xf0000;
/*
** increment all string pointers so the leading 'A' gets skipped,
** thus turning all occurrences of "ADNP ..." into "DNP ..."
*/
++dnpc_map.name;
for(i = 0; i < NUM_PARTITIONS; i++)
++partition_info[i].name;
higlvl_partition_info[1].size = DNP_WINDOW_SIZE -
CONFIG_MTD_DILNETPC_BOOTSIZE - 0x20000;
for(i = 0; i < NUM_HIGHLVL_PARTITIONS; i++)
++higlvl_partition_info[i].name;
}
printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n",
is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys);
dnpc_map.virt = ioremap_nocache(dnpc_map.phys, dnpc_map.size);
dnpc_map_flash(dnpc_map.phys, dnpc_map.size);
if (!dnpc_map.virt) {
printk("Failed to ioremap_nocache\n");
return -EIO;
}
simple_map_init(&dnpc_map);
printk("FLASH virtual address: 0x%p\n", dnpc_map.virt);
mymtd = do_map_probe("jedec_probe", &dnpc_map);
if (!mymtd)
mymtd = do_map_probe("cfi_probe", &dnpc_map);
/*
** If flash probes fail, try to make flashes accessible
** at least as ROM. Ajust erasesize in this case since
** the default one (128M) will break our partitioning
*/
if (!mymtd)
if((mymtd = do_map_probe("map_rom", &dnpc_map)))
mymtd->erasesize = 0x10000;
if (!mymtd) {
iounmap(dnpc_map.virt);
return -ENXIO;
}
mymtd->owner = THIS_MODULE;
/*
** Supply pointers to lowlvl_parts[] array to add_mtd_partitions()
** -> add_mtd_partitions() will _not_ register MTD devices for
** the partitions, but will instead store pointers to the MTD
** objects it creates into our lowlvl_parts[] array.
** NOTE: we arrange the pointers such that the sequence of the
** partitions gets re-arranged: partition #2 follows
** partition #0.
*/
partition_info[0].mtdp = &lowlvl_parts[0];
partition_info[1].mtdp = &lowlvl_parts[2];
partition_info[2].mtdp = &lowlvl_parts[1];
partition_info[3].mtdp = &lowlvl_parts[3];
add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
/*
** now create a virtual MTD device by concatenating the for partitions
** (in the sequence given by the lowlvl_parts[] array.
*/
merged_mtd = mtd_concat_create(lowlvl_parts, NUM_PARTITIONS, "(A)DNP Flash Concatenated");
if(merged_mtd)
{ /*
** now partition the new device the way we want it. This time,
** we do not supply mtd pointers in higlvl_partition_info, so
** add_mtd_partitions() will register the devices.
*/
add_mtd_partitions(merged_mtd, higlvl_partition_info, NUM_HIGHLVL_PARTITIONS);
}
return 0;
}
static void __exit cleanup_dnpc(void)
{
if(merged_mtd) {
del_mtd_partitions(merged_mtd);
mtd_concat_destroy(merged_mtd);
}
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
if (dnpc_map.virt) {
iounmap(dnpc_map.virt);
dnpc_unmap_flash();
dnpc_map.virt = NULL;
}
}
module_init(init_dnpc);
module_exit(cleanup_dnpc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sysgo Real-Time Solutions GmbH");
MODULE_DESCRIPTION("MTD map driver for SSV DIL/NetPC DNP & ADNP");

149
drivers/mtd/maps/dmv182.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,149 @@
/*
* drivers/mtd/maps/svme182.c
*
* Flash map driver for the Dy4 SVME182 board
*
* $Id: dmv182.c,v 1.5 2004/11/04 13:24:14 gleixner Exp $
*
* Copyright 2003-2004, TimeSys Corporation
*
* Based on the SVME181 flash map, by Tom Nelson, Dot4, Inc. for TimeSys Corp.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/errno.h>
/*
* This driver currently handles only the 16MiB user flash bank 1 on the
* board. It does not provide access to bank 0 (contains the Dy4 FFW), bank 2
* (VxWorks boot), or the optional 48MiB expansion flash.
*
* scott.wood@timesys.com: On the newer boards with 128MiB flash, it
* now supports the first 96MiB (the boot flash bank containing FFW
* is excluded). The VxWorks loader is in partition 1.
*/
#define FLASH_BASE_ADDR 0xf0000000
#define FLASH_BANK_SIZE (128*1024*1024)
MODULE_AUTHOR("Scott Wood, TimeSys Corporation <scott.wood@timesys.com>");
MODULE_DESCRIPTION("User-programmable flash device on the Dy4 SVME182 board");
MODULE_LICENSE("GPL");
static struct map_info svme182_map = {
.name = "Dy4 SVME182",
.bankwidth = 32,
.size = 128 * 1024 * 1024
};
#define BOOTIMAGE_PART_SIZE ((6*1024*1024)-RESERVED_PART_SIZE)
// Allow 6MiB for the kernel
#define NEW_BOOTIMAGE_PART_SIZE (6 * 1024 * 1024)
// Allow 1MiB for the bootloader
#define NEW_BOOTLOADER_PART_SIZE (1024 * 1024)
// Use the remaining 9MiB at the end of flash for the RFS
#define NEW_RFS_PART_SIZE (0x01000000 - NEW_BOOTLOADER_PART_SIZE - \
NEW_BOOTIMAGE_PART_SIZE)
static struct mtd_partition svme182_partitions[] = {
// The Lower PABS is only 128KiB, but the partition code doesn't
// like partitions that don't end on the largest erase block
// size of the device, even if all of the erase blocks in the
// partition are small ones. The hardware should prevent
// writes to the actual PABS areas.
{
name: "Lower PABS and CPU 0 bootloader or kernel",
size: 6*1024*1024,
offset: 0,
},
{
name: "Root Filesystem",
size: 10*1024*1024,
offset: MTDPART_OFS_NXTBLK
},
{
name: "CPU1 Bootloader",
size: 1024*1024,
offset: MTDPART_OFS_NXTBLK,
},
{
name: "Extra",
size: 110*1024*1024,
offset: MTDPART_OFS_NXTBLK
},
{
name: "Foundation Firmware and Upper PABS",
size: 1024*1024,
offset: MTDPART_OFS_NXTBLK,
mask_flags: MTD_WRITEABLE // read-only
}
};
static struct mtd_info *this_mtd;
static int __init init_svme182(void)
{
struct mtd_partition *partitions;
int num_parts = sizeof(svme182_partitions) / sizeof(struct mtd_partition);
partitions = svme182_partitions;
svme182_map.virt = ioremap(FLASH_BASE_ADDR, svme182_map.size);
if (svme182_map.virt == 0) {
printk("Failed to ioremap FLASH memory area.\n");
return -EIO;
}
simple_map_init(&svme182_map);
this_mtd = do_map_probe("cfi_probe", &svme182_map);
if (!this_mtd)
{
iounmap((void *)svme182_map.virt);
return -ENXIO;
}
printk(KERN_NOTICE "SVME182 flash device: %dMiB at 0x%08x\n",
this_mtd->size >> 20, FLASH_BASE_ADDR);
this_mtd->owner = THIS_MODULE;
add_mtd_partitions(this_mtd, partitions, num_parts);
return 0;
}
static void __exit cleanup_svme182(void)
{
if (this_mtd)
{
del_mtd_partitions(this_mtd);
map_destroy(this_mtd);
}
if (svme182_map.virt)
{
iounmap((void *)svme182_map.virt);
svme182_map.virt = 0;
}
return;
}
module_init(init_svme182);
module_exit(cleanup_svme182);

163
drivers/mtd/maps/ebony.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,163 @@
/*
* $Id: ebony.c,v 1.15 2004/12/09 18:39:54 holindho Exp $
*
* Mapping for Ebony user flash
*
* Matt Porter <mporter@kernel.crashing.org>
*
* Copyright 2002-2004 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/config.h>
#include <linux/version.h>
#include <asm/io.h>
#include <asm/ibm44x.h>
#include <platforms/4xx/ebony.h>
static struct mtd_info *flash;
static struct map_info ebony_small_map = {
.name = "Ebony small flash",
.size = EBONY_SMALL_FLASH_SIZE,
.bankwidth = 1,
};
static struct map_info ebony_large_map = {
.name = "Ebony large flash",
.size = EBONY_LARGE_FLASH_SIZE,
.bankwidth = 1,
};
static struct mtd_partition ebony_small_partitions[] = {
{
.name = "OpenBIOS",
.offset = 0x0,
.size = 0x80000,
}
};
static struct mtd_partition ebony_large_partitions[] = {
{
.name = "fs",
.offset = 0,
.size = 0x380000,
},
{
.name = "firmware",
.offset = 0x380000,
.size = 0x80000,
}
};
int __init init_ebony(void)
{
u8 fpga0_reg;
u8 __iomem *fpga0_adr;
unsigned long long small_flash_base, large_flash_base;
fpga0_adr = ioremap64(EBONY_FPGA_ADDR, 16);
if (!fpga0_adr)
return -ENOMEM;
fpga0_reg = readb(fpga0_adr);
iounmap(fpga0_adr);
if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
!EBONY_FLASH_SEL(fpga0_reg))
small_flash_base = EBONY_SMALL_FLASH_HIGH2;
else if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
EBONY_FLASH_SEL(fpga0_reg))
small_flash_base = EBONY_SMALL_FLASH_HIGH1;
else if (!EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
!EBONY_FLASH_SEL(fpga0_reg))
small_flash_base = EBONY_SMALL_FLASH_LOW2;
else
small_flash_base = EBONY_SMALL_FLASH_LOW1;
if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
!EBONY_ONBRD_FLASH_EN(fpga0_reg))
large_flash_base = EBONY_LARGE_FLASH_LOW;
else
large_flash_base = EBONY_LARGE_FLASH_HIGH;
ebony_small_map.phys = small_flash_base;
ebony_small_map.virt = ioremap64(small_flash_base,
ebony_small_map.size);
if (!ebony_small_map.virt) {
printk("Failed to ioremap flash\n");
return -EIO;
}
simple_map_init(&ebony_small_map);
flash = do_map_probe("jedec_probe", &ebony_small_map);
if (flash) {
flash->owner = THIS_MODULE;
add_mtd_partitions(flash, ebony_small_partitions,
ARRAY_SIZE(ebony_small_partitions));
} else {
printk("map probe failed for flash\n");
return -ENXIO;
}
ebony_large_map.phys = large_flash_base;
ebony_large_map.virt = ioremap64(large_flash_base,
ebony_large_map.size);
if (!ebony_large_map.virt) {
printk("Failed to ioremap flash\n");
return -EIO;
}
simple_map_init(&ebony_large_map);
flash = do_map_probe("jedec_probe", &ebony_large_map);
if (flash) {
flash->owner = THIS_MODULE;
add_mtd_partitions(flash, ebony_large_partitions,
ARRAY_SIZE(ebony_large_partitions));
} else {
printk("map probe failed for flash\n");
return -ENXIO;
}
return 0;
}
static void __exit cleanup_ebony(void)
{
if (flash) {
del_mtd_partitions(flash);
map_destroy(flash);
}
if (ebony_small_map.virt) {
iounmap(ebony_small_map.virt);
ebony_small_map.virt = NULL;
}
if (ebony_large_map.virt) {
iounmap(ebony_large_map.virt);
ebony_large_map.virt = NULL;
}
}
module_init(init_ebony);
module_exit(cleanup_ebony);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
MODULE_DESCRIPTION("MTD map and partitions for IBM 440GP Ebony boards");

147
drivers/mtd/maps/edb7312.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,147 @@
/*
* $Id: edb7312.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $
*
* Handle mapping of the NOR flash on Cogent EDB7312 boards
*
* Copyright 2002 SYSGO Real-Time Solutions GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/config.h>
#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
#endif
#define WINDOW_ADDR 0x00000000 /* physical properties of flash */
#define WINDOW_SIZE 0x01000000
#define BUSWIDTH 2
#define FLASH_BLOCKSIZE_MAIN 0x20000
#define FLASH_NUMBLOCKS_MAIN 128
/* can be "cfi_probe", "jedec_probe", "map_rom", NULL }; */
#define PROBETYPES { "cfi_probe", NULL }
#define MSG_PREFIX "EDB7312-NOR:" /* prefix for our printk()'s */
#define MTDID "edb7312-nor" /* for mtdparts= partitioning */
static struct mtd_info *mymtd;
struct map_info edb7312nor_map = {
.name = "NOR flash on EDB7312",
.size = WINDOW_SIZE,
.bankwidth = BUSWIDTH,
.phys = WINDOW_ADDR,
};
#ifdef CONFIG_MTD_PARTITIONS
/*
* MTD partitioning stuff
*/
static struct mtd_partition static_partitions[3] =
{
{
.name = "ARMboot",
.size = 0x40000,
.offset = 0
},
{
.name = "Kernel",
.size = 0x200000,
.offset = 0x40000
},
{
.name = "RootFS",
.size = 0xDC0000,
.offset = 0x240000
},
};
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
#endif
static int mtd_parts_nb = 0;
static struct mtd_partition *mtd_parts = 0;
int __init init_edb7312nor(void)
{
static const char *rom_probe_types[] = PROBETYPES;
const char **type;
const char *part_type = 0;
printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n",
WINDOW_SIZE, WINDOW_ADDR);
edb7312nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!edb7312nor_map.virt) {
printk(MSG_PREFIX "failed to ioremap\n");
return -EIO;
}
simple_map_init(&edb7312nor_map);
mymtd = 0;
type = rom_probe_types;
for(; !mymtd && *type; type++) {
mymtd = do_map_probe(*type, &edb7312nor_map);
}
if (mymtd) {
mymtd->owner = THIS_MODULE;
#ifdef CONFIG_MTD_PARTITIONS
mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID);
if (mtd_parts_nb > 0)
part_type = "detected";
if (mtd_parts_nb == 0)
{
mtd_parts = static_partitions;
mtd_parts_nb = ARRAY_SIZE(static_partitions);
part_type = "static";
}
#endif
add_mtd_device(mymtd);
if (mtd_parts_nb == 0)
printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
else
{
printk(KERN_NOTICE MSG_PREFIX
"using %s partition definition\n", part_type);
add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb);
}
return 0;
}
iounmap((void *)edb7312nor_map.virt);
return -ENXIO;
}
static void __exit cleanup_edb7312nor(void)
{
if (mymtd) {
del_mtd_device(mymtd);
map_destroy(mymtd);
}
if (edb7312nor_map.virt) {
iounmap((void *)edb7312nor_map.virt);
edb7312nor_map.virt = 0;
}
}
module_init(init_edb7312nor);
module_exit(cleanup_edb7312nor);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
MODULE_DESCRIPTION("Generic configurable MTD map driver");

228
drivers/mtd/maps/elan-104nc.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,228 @@
/* elan-104nc.c -- MTD map driver for Arcom Control Systems ELAN-104NC
Copyright (C) 2000 Arcom Control System Ltd
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
$Id: elan-104nc.c,v 1.25 2004/11/28 09:40:39 dwmw2 Exp $
The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x16
mode. This drivers uses the CFI probe and Intel Extended Command Set drivers.
The flash is accessed as follows:
32 kbyte memory window at 0xb0000-0xb7fff
16 bit I/O port (0x22) for some sort of paging.
The single flash device is divided into 3 partition which appear as separate
MTD devices.
Linux thinks that the I/O port is used by the PIC and hence check_region() will
always fail. So we don't do it. I just hope it doesn't break anything.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#define WINDOW_START 0xb0000
/* Number of bits in offset. */
#define WINDOW_SHIFT 15
#define WINDOW_LENGTH (1 << WINDOW_SHIFT)
/* The bits for the offset into the window. */
#define WINDOW_MASK (WINDOW_LENGTH-1)
#define PAGE_IO 0x22
#define PAGE_IO_SIZE 2
static volatile int page_in_window = -1; // Current page in window.
static void __iomem *iomapadr;
static DEFINE_SPINLOCK(elan_104nc_spin);
/* partition_info gives details on the logical partitions that the split the
* single flash device into. If the size if zero we use up to the end of the
* device. */
static struct mtd_partition partition_info[]={
{ .name = "ELAN-104NC flash boot partition",
.offset = 0,
.size = 640*1024 },
{ .name = "ELAN-104NC flash partition 1",
.offset = 640*1024,
.size = 896*1024 },
{ .name = "ELAN-104NC flash partition 2",
.offset = (640+896)*1024 }
};
#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
/*
* If no idea what is going on here. This is taken from the FlashFX stuff.
*/
#define ROMCS 1
static inline void elan_104nc_setup(void)
{
u16 t;
outw( 0x0023 + ROMCS*2, PAGE_IO );
t=inb( PAGE_IO+1 );
t=(t & 0xf9) | 0x04;
outw( ((0x0023 + ROMCS*2) | (t << 8)), PAGE_IO );
}
static inline void elan_104nc_page(struct map_info *map, unsigned long ofs)
{
unsigned long page = ofs >> WINDOW_SHIFT;
if( page!=page_in_window ) {
int cmd1;
int cmd2;
cmd1=(page & 0x700) + 0x0833 + ROMCS*0x4000;
cmd2=((page & 0xff) << 8) + 0x0032;
outw( cmd1, PAGE_IO );
outw( cmd2, PAGE_IO );
page_in_window = page;
}
}
static map_word elan_104nc_read16(struct map_info *map, unsigned long ofs)
{
map_word ret;
spin_lock(&elan_104nc_spin);
elan_104nc_page(map, ofs);
ret.x[0] = readw(iomapadr + (ofs & WINDOW_MASK));
spin_unlock(&elan_104nc_spin);
return ret;
}
static void elan_104nc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
while (len) {
unsigned long thislen = len;
if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
spin_lock(&elan_104nc_spin);
elan_104nc_page(map, from);
memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen);
spin_unlock(&elan_104nc_spin);
to += thislen;
from += thislen;
len -= thislen;
}
}
static void elan_104nc_write16(struct map_info *map, map_word d, unsigned long adr)
{
spin_lock(&elan_104nc_spin);
elan_104nc_page(map, adr);
writew(d.x[0], iomapadr + (adr & WINDOW_MASK));
spin_unlock(&elan_104nc_spin);
}
static void elan_104nc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
while(len) {
unsigned long thislen = len;
if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
spin_lock(&elan_104nc_spin);
elan_104nc_page(map, to);
memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen);
spin_unlock(&elan_104nc_spin);
to += thislen;
from += thislen;
len -= thislen;
}
}
static struct map_info elan_104nc_map = {
.name = "ELAN-104NC flash",
.phys = NO_XIP,
.size = 8*1024*1024, /* this must be set to a maximum possible amount
of flash so the cfi probe routines find all
the chips */
.bankwidth = 2,
.read = elan_104nc_read16,
.copy_from = elan_104nc_copy_from,
.write = elan_104nc_write16,
.copy_to = elan_104nc_copy_to
};
/* MTD device for all of the flash. */
static struct mtd_info *all_mtd;
static void cleanup_elan_104nc(void)
{
if( all_mtd ) {
del_mtd_partitions( all_mtd );
map_destroy( all_mtd );
}
iounmap(iomapadr);
}
static int __init init_elan_104nc(void)
{
/* Urg! We use I/O port 0x22 without request_region()ing it,
because it's already allocated to the PIC. */
iomapadr = ioremap(WINDOW_START, WINDOW_LENGTH);
if (!iomapadr) {
printk( KERN_ERR"%s: failed to ioremap memory region\n",
elan_104nc_map.name );
return -EIO;
}
printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n",
elan_104nc_map.name,
PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1,
WINDOW_START, WINDOW_START+WINDOW_LENGTH-1 );
elan_104nc_setup();
/* Probe for chip. */
all_mtd = do_map_probe("cfi_probe", &elan_104nc_map );
if( !all_mtd ) {
cleanup_elan_104nc();
return -ENXIO;
}
all_mtd->owner = THIS_MODULE;
/* Create MTD devices for each partition. */
add_mtd_partitions( all_mtd, partition_info, NUM_PARTITIONS );
return 0;
}
module_init(init_elan_104nc);
module_exit(cleanup_elan_104nc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arcom Control Systems Ltd.");
MODULE_DESCRIPTION("MTD map driver for Arcom Control Systems ELAN-104NC");

176
drivers/mtd/maps/epxa10db-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,176 @@
/*
* Flash memory access on EPXA based devices
*
* (C) 2000 Nicolas Pitre <nico@cam.org>
* Copyright (C) 2001 Altera Corporation
* Copyright (C) 2001 Red Hat, Inc.
*
* $Id: epxa10db-flash.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/hardware.h>
#ifdef CONFIG_EPXA10DB
#define BOARD_NAME "EPXA10DB"
#else
#define BOARD_NAME "EPXA1DB"
#endif
static int nr_parts = 0;
static struct mtd_partition *parts;
static struct mtd_info *mymtd;
static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
static struct map_info epxa_map = {
.name = "EPXA flash",
.size = FLASH_SIZE,
.bankwidth = 2,
.phys = FLASH_START,
};
static const char *probes[] = { "RedBoot", "afs", NULL };
static int __init epxa_mtd_init(void)
{
int i;
printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
epxa_map.virt = ioremap(FLASH_START, FLASH_SIZE);
if (!epxa_map.virt) {
printk("Failed to ioremap %s flash\n",BOARD_NAME);
return -EIO;
}
simple_map_init(&epxa_map);
mymtd = do_map_probe("cfi_probe", &epxa_map);
if (!mymtd) {
iounmap((void *)epxa_map.virt);
return -ENXIO;
}
mymtd->owner = THIS_MODULE;
/* Unlock the flash device. */
if(mymtd->unlock){
for (i=0; i<mymtd->numeraseregions;i++){
int j;
for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
}
}
}
#ifdef CONFIG_MTD_PARTITIONS
nr_parts = parse_mtd_partitions(mymtd, probes, &parts, 0);
if (nr_parts > 0) {
add_mtd_partitions(mymtd, parts, nr_parts);
return 0;
}
#endif
/* No recognised partitioning schemes found - use defaults */
nr_parts = epxa_default_partitions(mymtd, &parts);
if (nr_parts > 0) {
add_mtd_partitions(mymtd, parts, nr_parts);
return 0;
}
/* If all else fails... */
add_mtd_device(mymtd);
return 0;
}
static void __exit epxa_mtd_cleanup(void)
{
if (mymtd) {
if (nr_parts)
del_mtd_partitions(mymtd);
else
del_mtd_device(mymtd);
map_destroy(mymtd);
}
if (epxa_map.virt) {
iounmap((void *)epxa_map.virt);
epxa_map.virt = 0;
}
}
/*
* This will do for now, once we decide which bootldr we're finally
* going to use then we'll remove this function and do it properly
*
* Partions are currently (as offsets from base of flash):
* 0x00000000 - 0x003FFFFF - bootloader (!)
* 0x00400000 - 0x00FFFFFF - Flashdisk
*/
static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
{
struct mtd_partition *parts;
int ret, i;
int npartitions = 0;
char *names;
const char *name = "jffs";
printk("Using default partitions for %s\n",BOARD_NAME);
npartitions=1;
parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL);
memzero(parts,npartitions*sizeof(*parts)+strlen(name));
if (!parts) {
ret = -ENOMEM;
goto out;
}
i=0;
names = (char *)&parts[npartitions];
parts[i].name = names;
names += strlen(name) + 1;
strcpy(parts[i].name, name);
#ifdef CONFIG_EPXA10DB
parts[i].size = FLASH_SIZE-0x00400000;
parts[i].offset = 0x00400000;
#else
parts[i].size = FLASH_SIZE-0x00180000;
parts[i].offset = 0x00180000;
#endif
out:
*pparts = parts;
return npartitions;
}
module_init(epxa_mtd_init);
module_exit(epxa_mtd_cleanup);
MODULE_AUTHOR("Clive Davies");
MODULE_DESCRIPTION("Altera epxa mtd flash map");
MODULE_LICENSE("GPL");

271
drivers/mtd/maps/fortunet.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,271 @@
/* fortunet.c memory map
*
* $Id: fortunet.c,v 1.9 2004/11/04 13:24:14 gleixner Exp $
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#define MAX_NUM_REGIONS 4
#define MAX_NUM_PARTITIONS 8
#define DEF_WINDOW_ADDR_PHY 0x00000000
#define DEF_WINDOW_SIZE 0x00800000 // 8 Mega Bytes
#define MTD_FORTUNET_PK "MTD FortuNet: "
#define MAX_NAME_SIZE 128
struct map_region
{
int window_addr_physical;
int altbankwidth;
struct map_info map_info;
struct mtd_info *mymtd;
struct mtd_partition parts[MAX_NUM_PARTITIONS];
char map_name[MAX_NAME_SIZE];
char parts_name[MAX_NUM_PARTITIONS][MAX_NAME_SIZE];
};
static struct map_region map_regions[MAX_NUM_REGIONS];
static int map_regions_set[MAX_NUM_REGIONS] = {0,0,0,0};
static int map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0};
struct map_info default_map = {
.size = DEF_WINDOW_SIZE,
.bankwidth = 4,
};
static char * __init get_string_option(char *dest,int dest_size,char *sor)
{
if(!dest_size)
return sor;
dest_size--;
while(*sor)
{
if(*sor==',')
{
sor++;
break;
}
else if(*sor=='\"')
{
sor++;
while(*sor)
{
if(*sor=='\"')
{
sor++;
break;
}
*dest = *sor;
dest++;
sor++;
dest_size--;
if(!dest_size)
{
*dest = 0;
return sor;
}
}
}
else
{
*dest = *sor;
dest++;
sor++;
dest_size--;
if(!dest_size)
{
*dest = 0;
return sor;
}
}
}
*dest = 0;
return sor;
}
static int __init MTD_New_Region(char *line)
{
char string[MAX_NAME_SIZE];
int params[6];
get_options (get_string_option(string,sizeof(string),line),6,params);
if(params[0]<1)
{
printk(MTD_FORTUNET_PK "Bad parameters for MTD Region "
" name,region-number[,base,size,bankwidth,altbankwidth]\n");
return 1;
}
if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
{
printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
params[1],MAX_NUM_REGIONS-1);
return 1;
}
memset(&map_regions[params[1]],0,sizeof(map_regions[params[1]]));
memcpy(&map_regions[params[1]].map_info,
&default_map,sizeof(map_regions[params[1]].map_info));
map_regions_set[params[1]] = 1;
map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY;
map_regions[params[1]].altbankwidth = 2;
map_regions[params[1]].mymtd = NULL;
map_regions[params[1]].map_info.name = map_regions[params[1]].map_name;
strcpy(map_regions[params[1]].map_info.name,string);
if(params[0]>1)
{
map_regions[params[1]].window_addr_physical = params[2];
}
if(params[0]>2)
{
map_regions[params[1]].map_info.size = params[3];
}
if(params[0]>3)
{
map_regions[params[1]].map_info.bankwidth = params[4];
}
if(params[0]>4)
{
map_regions[params[1]].altbankwidth = params[5];
}
return 1;
}
static int __init MTD_New_Partition(char *line)
{
char string[MAX_NAME_SIZE];
int params[4];
get_options (get_string_option(string,sizeof(string),line),4,params);
if(params[0]<3)
{
printk(MTD_FORTUNET_PK "Bad parameters for MTD Partition "
" name,region-number,size,offset\n");
return 1;
}
if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
{
printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
params[1],MAX_NUM_REGIONS-1);
return 1;
}
if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS)
{
printk(MTD_FORTUNET_PK "Out of space for partition in this region\n");
return 1;
}
map_regions[params[1]].parts[map_regions_parts[params[1]]].name =
map_regions[params[1]]. parts_name[map_regions_parts[params[1]]];
strcpy(map_regions[params[1]].parts[map_regions_parts[params[1]]].name,string);
map_regions[params[1]].parts[map_regions_parts[params[1]]].size =
params[2];
map_regions[params[1]].parts[map_regions_parts[params[1]]].offset =
params[3];
map_regions[params[1]].parts[map_regions_parts[params[1]]].mask_flags = 0;
map_regions_parts[params[1]]++;
return 1;
}
__setup("MTD_Region=", MTD_New_Region);
__setup("MTD_Partition=", MTD_New_Partition);
/* Backwards-spelling-compatibility */
__setup("MTD_Partion=", MTD_New_Partition);
int __init init_fortunet(void)
{
int ix,iy;
for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++)
{
if(map_regions_parts[ix]&&(!map_regions_set[ix]))
{
printk(MTD_FORTUNET_PK "Region %d is not setup (Setting to default)\n",
ix);
memset(&map_regions[ix],0,sizeof(map_regions[ix]));
memcpy(&map_regions[ix].map_info,&default_map,
sizeof(map_regions[ix].map_info));
map_regions_set[ix] = 1;
map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY;
map_regions[ix].altbankwidth = 2;
map_regions[ix].mymtd = NULL;
map_regions[ix].map_info.name = map_regions[ix].map_name;
strcpy(map_regions[ix].map_info.name,"FORTUNET");
}
if(map_regions_set[ix])
{
iy++;
printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at physically "
" address %x size %x\n",
map_regions[ix].map_info.name,
map_regions[ix].window_addr_physical,
map_regions[ix].map_info.size);
map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical,
map_regions[ix].map_info.virt =
ioremap_nocache(
map_regions[ix].window_addr_physical,
map_regions[ix].map_info.size);
if(!map_regions[ix].map_info.virt)
{
printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n",
map_regions[ix].map_info.name);
return -ENXIO;
}
simple_map_init(&map_regions[ix].map_info);
printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n",
map_regions[ix].map_info.name,
map_regions[ix].map_info.virt);
map_regions[ix].mymtd = do_map_probe("cfi_probe",
&map_regions[ix].map_info);
if((!map_regions[ix].mymtd)&&(
map_regions[ix].altbankwidth!=map_regions[ix].map_info.bankwidth))
{
printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth "
"for %s flash.\n",
map_regions[ix].map_info.name);
map_regions[ix].map_info.bankwidth =
map_regions[ix].altbankwidth;
map_regions[ix].mymtd = do_map_probe("cfi_probe",
&map_regions[ix].map_info);
}
map_regions[ix].mymtd->owner = THIS_MODULE;
add_mtd_partitions(map_regions[ix].mymtd,
map_regions[ix].parts,map_regions_parts[ix]);
}
}
if(iy)
return 0;
return -ENXIO;
}
static void __exit cleanup_fortunet(void)
{
int ix;
for(ix=0;ix<MAX_NUM_REGIONS;ix++)
{
if(map_regions_set[ix])
{
if( map_regions[ix].mymtd )
{
del_mtd_partitions( map_regions[ix].mymtd );
map_destroy( map_regions[ix].mymtd );
}
iounmap((void *)map_regions[ix].map_info.virt);
}
}
}
module_init(init_fortunet);
module_exit(cleanup_fortunet);
MODULE_AUTHOR("FortuNet, Inc.");
MODULE_DESCRIPTION("MTD map driver for FortuNet boards");

144
drivers/mtd/maps/h720x-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,144 @@
/*
* Flash memory access on Hynix GMS30C7201/HMS30C7202 based
* evaluation boards
*
* $Id: h720x-flash.c,v 1.11 2004/11/04 13:24:14 gleixner Exp $
*
* (C) 2002 Jungjun Kim <jungjun.kim@hynix.com>
* 2003 Thomas Gleixner <tglx@linutronix.de>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/hardware.h>
#include <asm/io.h>
static struct mtd_info *mymtd;
static struct map_info h720x_map = {
.name = "H720X",
.bankwidth = 4,
.size = FLASH_SIZE,
.phys = FLASH_PHYS,
};
static struct mtd_partition h720x_partitions[] = {
{
.name = "ArMon",
.size = 0x00080000,
.offset = 0,
.mask_flags = MTD_WRITEABLE
},{
.name = "Env",
.size = 0x00040000,
.offset = 0x00080000,
.mask_flags = MTD_WRITEABLE
},{
.name = "Kernel",
.size = 0x00180000,
.offset = 0x000c0000,
.mask_flags = MTD_WRITEABLE
},{
.name = "Ramdisk",
.size = 0x00400000,
.offset = 0x00240000,
.mask_flags = MTD_WRITEABLE
},{
.name = "jffs2",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND
}
};
#define NUM_PARTITIONS (sizeof(h720x_partitions)/sizeof(h720x_partitions[0]))
static int nr_mtd_parts;
static struct mtd_partition *mtd_parts;
static const char *probes[] = { "cmdlinepart", NULL };
/*
* Initialize FLASH support
*/
int __init h720x_mtd_init(void)
{
char *part_type = NULL;
h720x_map.virt = ioremap(FLASH_PHYS, FLASH_SIZE);
if (!h720x_map.virt) {
printk(KERN_ERR "H720x-MTD: ioremap failed\n");
return -EIO;
}
simple_map_init(&h720x_map);
// Probe for flash bankwidth 4
printk (KERN_INFO "H720x-MTD probing 32bit FLASH\n");
mymtd = do_map_probe("cfi_probe", &h720x_map);
if (!mymtd) {
printk (KERN_INFO "H720x-MTD probing 16bit FLASH\n");
// Probe for bankwidth 2
h720x_map.bankwidth = 2;
mymtd = do_map_probe("cfi_probe", &h720x_map);
}
if (mymtd) {
mymtd->owner = THIS_MODULE;
#ifdef CONFIG_MTD_PARTITIONS
nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
if (nr_mtd_parts > 0)
part_type = "command line";
#endif
if (nr_mtd_parts <= 0) {
mtd_parts = h720x_partitions;
nr_mtd_parts = NUM_PARTITIONS;
part_type = "builtin";
}
printk(KERN_INFO "Using %s partition table\n", part_type);
add_mtd_partitions(mymtd, mtd_parts, nr_mtd_parts);
return 0;
}
iounmap((void *)h720x_map.virt);
return -ENXIO;
}
/*
* Cleanup
*/
static void __exit h720x_mtd_cleanup(void)
{
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
/* Free partition info, if commandline partition was used */
if (mtd_parts && (mtd_parts != h720x_partitions))
kfree (mtd_parts);
if (h720x_map.virt) {
iounmap((void *)h720x_map.virt);
h720x_map.virt = 0;
}
}
module_init(h720x_mtd_init);
module_exit(h720x_mtd_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
MODULE_DESCRIPTION("MTD map driver for Hynix evaluation boards");

383
drivers/mtd/maps/ichxrom.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,383 @@
/*
* ichxrom.c
*
* Normal mappings of chips in physical memory
* $Id: ichxrom.c,v 1.16 2004/11/28 09:40:39 dwmw2 Exp $
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/cfi.h>
#include <linux/mtd/flashchip.h>
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/list.h>
#define xstr(s) str(s)
#define str(s) #s
#define MOD_NAME xstr(KBUILD_BASENAME)
#define ADDRESS_NAME_LEN 18
#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
#define BIOS_CNTL 0x4e
#define FWH_DEC_EN1 0xE3
#define FWH_DEC_EN2 0xF0
#define FWH_SEL1 0xE8
#define FWH_SEL2 0xEE
struct ichxrom_window {
void __iomem* virt;
unsigned long phys;
unsigned long size;
struct list_head maps;
struct resource rsrc;
struct pci_dev *pdev;
};
struct ichxrom_map_info {
struct list_head list;
struct map_info map;
struct mtd_info *mtd;
struct resource rsrc;
char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
};
static struct ichxrom_window ichxrom_window = {
.maps = LIST_HEAD_INIT(ichxrom_window.maps),
};
static void ichxrom_cleanup(struct ichxrom_window *window)
{
struct ichxrom_map_info *map, *scratch;
u16 word;
/* Disable writes through the rom window */
pci_read_config_word(window->pdev, BIOS_CNTL, &word);
pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1);
/* Free all of the mtd devices */
list_for_each_entry_safe(map, scratch, &window->maps, list) {
if (map->rsrc.parent)
release_resource(&map->rsrc);
del_mtd_device(map->mtd);
map_destroy(map->mtd);
list_del(&map->list);
kfree(map);
}
if (window->rsrc.parent)
release_resource(&window->rsrc);
if (window->virt) {
iounmap(window->virt);
window->virt = NULL;
window->phys = 0;
window->size = 0;
window->pdev = NULL;
}
}
static int __devinit ichxrom_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
struct ichxrom_window *window = &ichxrom_window;
struct ichxrom_map_info *map = NULL;
unsigned long map_top;
u8 byte;
u16 word;
/* For now I just handle the ichx and I assume there
* are not a lot of resources up at the top of the address
* space. It is possible to handle other devices in the
* top 16MB but it is very painful. Also since
* you can only really attach a FWH to an ICHX there
* a number of simplifications you can make.
*
* Also you can page firmware hubs if an 8MB window isn't enough
* but don't currently handle that case either.
*/
window->pdev = pdev;
/* Find a region continuous to the end of the ROM window */
window->phys = 0;
pci_read_config_byte(pdev, FWH_DEC_EN1, &byte);
if (byte == 0xff) {
window->phys = 0xffc00000;
pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
if ((byte & 0x0f) == 0x0f) {
window->phys = 0xff400000;
}
else if ((byte & 0x0e) == 0x0e) {
window->phys = 0xff500000;
}
else if ((byte & 0x0c) == 0x0c) {
window->phys = 0xff600000;
}
else if ((byte & 0x08) == 0x08) {
window->phys = 0xff700000;
}
}
else if ((byte & 0xfe) == 0xfe) {
window->phys = 0xffc80000;
}
else if ((byte & 0xfc) == 0xfc) {
window->phys = 0xffd00000;
}
else if ((byte & 0xf8) == 0xf8) {
window->phys = 0xffd80000;
}
else if ((byte & 0xf0) == 0xf0) {
window->phys = 0xffe00000;
}
else if ((byte & 0xe0) == 0xe0) {
window->phys = 0xffe80000;
}
else if ((byte & 0xc0) == 0xc0) {
window->phys = 0xfff00000;
}
else if ((byte & 0x80) == 0x80) {
window->phys = 0xfff80000;
}
if (window->phys == 0) {
printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
goto out;
}
window->phys -= 0x400000UL;
window->size = (0xffffffffUL - window->phys) + 1UL;
/* Enable writes through the rom window */
pci_read_config_word(pdev, BIOS_CNTL, &word);
if (!(word & 1) && (word & (1<<1))) {
/* The BIOS will generate an error if I enable
* this device, so don't even try.
*/
printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n");
goto out;
}
pci_write_config_word(pdev, BIOS_CNTL, word | 1);
/*
* Try to reserve the window mem region. If this fails then
* it is likely due to the window being "reseved" by the BIOS.
*/
window->rsrc.name = MOD_NAME;
window->rsrc.start = window->phys;
window->rsrc.end = window->phys + window->size - 1;
window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
if (request_resource(&iomem_resource, &window->rsrc)) {
window->rsrc.parent = NULL;
printk(KERN_DEBUG MOD_NAME
": %s(): Unable to register resource"
" 0x%.08lx-0x%.08lx - kernel bug?\n",
__func__,
window->rsrc.start, window->rsrc.end);
}
/* Map the firmware hub into my address space. */
window->virt = ioremap_nocache(window->phys, window->size);
if (!window->virt) {
printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
window->phys, window->size);
goto out;
}
/* Get the first address to look for an rom chip at */
map_top = window->phys;
if ((window->phys & 0x3fffff) != 0) {
map_top = window->phys + 0x400000;
}
#if 1
/* The probe sequence run over the firmware hub lock
* registers sets them to 0x7 (no access).
* Probe at most the last 4M of the address space.
*/
if (map_top < 0xffc00000) {
map_top = 0xffc00000;
}
#endif
/* Loop through and look for rom chips */
while((map_top - 1) < 0xffffffffUL) {
struct cfi_private *cfi;
unsigned long offset;
int i;
if (!map) {
map = kmalloc(sizeof(*map), GFP_KERNEL);
}
if (!map) {
printk(KERN_ERR MOD_NAME ": kmalloc failed");
goto out;
}
memset(map, 0, sizeof(*map));
INIT_LIST_HEAD(&map->list);
map->map.name = map->map_name;
map->map.phys = map_top;
offset = map_top - window->phys;
map->map.virt = (void __iomem *)
(((unsigned long)(window->virt)) + offset);
map->map.size = 0xffffffffUL - map_top + 1UL;
/* Set the name of the map to the address I am trying */
sprintf(map->map_name, "%s @%08lx",
MOD_NAME, map->map.phys);
/* Firmware hubs only use vpp when being programmed
* in a factory setting. So in-place programming
* needs to use a different method.
*/
for(map->map.bankwidth = 32; map->map.bankwidth;
map->map.bankwidth >>= 1)
{
char **probe_type;
/* Skip bankwidths that are not supported */
if (!map_bankwidth_supported(map->map.bankwidth))
continue;
/* Setup the map methods */
simple_map_init(&map->map);
/* Try all of the probe methods */
probe_type = rom_probe_types;
for(; *probe_type; probe_type++) {
map->mtd = do_map_probe(*probe_type, &map->map);
if (map->mtd)
goto found;
}
}
map_top += ROM_PROBE_STEP_SIZE;
continue;
found:
/* Trim the size if we are larger than the map */
if (map->mtd->size > map->map.size) {
printk(KERN_WARNING MOD_NAME
" rom(%u) larger than window(%lu). fixing...\n",
map->mtd->size, map->map.size);
map->mtd->size = map->map.size;
}
if (window->rsrc.parent) {
/*
* Registering the MTD device in iomem may not be possible
* if there is a BIOS "reserved" and BUSY range. If this
* fails then continue anyway.
*/
map->rsrc.name = map->map_name;
map->rsrc.start = map->map.phys;
map->rsrc.end = map->map.phys + map->mtd->size - 1;
map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
if (request_resource(&window->rsrc, &map->rsrc)) {
printk(KERN_ERR MOD_NAME
": cannot reserve MTD resource\n");
map->rsrc.parent = NULL;
}
}
/* Make the whole region visible in the map */
map->map.virt = window->virt;
map->map.phys = window->phys;
cfi = map->map.fldrv_priv;
for(i = 0; i < cfi->numchips; i++) {
cfi->chips[i].start += offset;
}
/* Now that the mtd devices is complete claim and export it */
map->mtd->owner = THIS_MODULE;
if (add_mtd_device(map->mtd)) {
map_destroy(map->mtd);
map->mtd = NULL;
goto out;
}
/* Calculate the new value of map_top */
map_top += map->mtd->size;
/* File away the map structure */
list_add(&map->list, &window->maps);
map = NULL;
}
out:
/* Free any left over map structures */
if (map) {
kfree(map);
}
/* See if I have any map structures */
if (list_empty(&window->maps)) {
ichxrom_cleanup(window);
return -ENODEV;
}
return 0;
}
static void __devexit ichxrom_remove_one (struct pci_dev *pdev)
{
struct ichxrom_window *window = &ichxrom_window;
ichxrom_cleanup(window);
}
static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
PCI_ANY_ID, PCI_ANY_ID, },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, ichxrom_pci_tbl);
#if 0
static struct pci_driver ichxrom_driver = {
.name = MOD_NAME,
.id_table = ichxrom_pci_tbl,
.probe = ichxrom_init_one,
.remove = ichxrom_remove_one,
};
#endif
static int __init init_ichxrom(void)
{
struct pci_dev *pdev;
struct pci_device_id *id;
pdev = NULL;
for (id = ichxrom_pci_tbl; id->vendor; id++) {
pdev = pci_find_device(id->vendor, id->device, NULL);
if (pdev) {
break;
}
}
if (pdev) {
return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]);
}
return -ENXIO;
#if 0
return pci_module_init(&ichxrom_driver);
#endif
}
static void __exit cleanup_ichxrom(void)
{
ichxrom_remove_one(ichxrom_window.pdev);
}
module_init(init_ichxrom);
module_exit(cleanup_ichxrom);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ICHX southbridge");

161
drivers/mtd/maps/impa7.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,161 @@
/*
* $Id: impa7.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $
*
* Handle mapping of the NOR flash on implementa A7 boards
*
* Copyright 2002 SYSGO Real-Time Solutions GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/config.h>
#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
#endif
#define WINDOW_ADDR0 0x00000000 /* physical properties of flash */
#define WINDOW_SIZE0 0x00800000
#define WINDOW_ADDR1 0x10000000 /* physical properties of flash */
#define WINDOW_SIZE1 0x00800000
#define NUM_FLASHBANKS 2
#define BUSWIDTH 4
/* can be { "cfi_probe", "jedec_probe", "map_rom", NULL } */
#define PROBETYPES { "jedec_probe", NULL }
#define MSG_PREFIX "impA7:" /* prefix for our printk()'s */
#define MTDID "impa7-%d" /* for mtdparts= partitioning */
static struct mtd_info *impa7_mtd[NUM_FLASHBANKS];
static struct map_info impa7_map[NUM_FLASHBANKS] = {
{
.name = "impA7 NOR Flash Bank #0",
.size = WINDOW_SIZE0,
.bankwidth = BUSWIDTH,
},
{
.name = "impA7 NOR Flash Bank #1",
.size = WINDOW_SIZE1,
.bankwidth = BUSWIDTH,
},
};
#ifdef CONFIG_MTD_PARTITIONS
/*
* MTD partitioning stuff
*/
static struct mtd_partition static_partitions[] =
{
{
.name = "FileSystem",
.size = 0x800000,
.offset = 0x00000000
},
};
static int mtd_parts_nb[NUM_FLASHBANKS];
static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
#endif
static const char *probes[] = { "cmdlinepart", NULL };
int __init init_impa7(void)
{
static const char *rom_probe_types[] = PROBETYPES;
const char **type;
const char *part_type = 0;
int i;
static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
{ WINDOW_ADDR0, WINDOW_SIZE0 },
{ WINDOW_ADDR1, WINDOW_SIZE1 },
};
int devicesfound = 0;
for(i=0; i<NUM_FLASHBANKS; i++)
{
printk(KERN_NOTICE MSG_PREFIX "probing 0x%08lx at 0x%08lx\n",
pt[i].size, pt[i].addr);
impa7_map[i].phys = pt[i].addr;
impa7_map[i].virt = ioremap(pt[i].addr, pt[i].size);
if (!impa7_map[i].virt) {
printk(MSG_PREFIX "failed to ioremap\n");
return -EIO;
}
simple_map_init(&impa7_map[i]);
impa7_mtd[i] = 0;
type = rom_probe_types;
for(; !impa7_mtd[i] && *type; type++) {
impa7_mtd[i] = do_map_probe(*type, &impa7_map[i]);
}
if (impa7_mtd[i]) {
impa7_mtd[i]->owner = THIS_MODULE;
devicesfound++;
#ifdef CONFIG_MTD_PARTITIONS
mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i],
probes,
&mtd_parts[i],
0);
if (mtd_parts_nb[i] > 0) {
part_type = "command line";
} else {
mtd_parts[i] = static_partitions;
mtd_parts_nb[i] = ARRAY_SIZE(static_partitions);
part_type = "static";
}
printk(KERN_NOTICE MSG_PREFIX
"using %s partition definition\n",
part_type);
add_mtd_partitions(impa7_mtd[i],
mtd_parts[i], mtd_parts_nb[i]);
#else
add_mtd_device(impa7_mtd[i]);
#endif
}
else
iounmap((void *)impa7_map[i].virt);
}
return devicesfound == 0 ? -ENXIO : 0;
}
static void __exit cleanup_impa7(void)
{
int i;
for (i=0; i<NUM_FLASHBANKS; i++) {
if (impa7_mtd[i]) {
#ifdef CONFIG_MTD_PARTITIONS
del_mtd_partitions(impa7_mtd[i]);
#else
del_mtd_device(impa7_mtd[i]);
#endif
map_destroy(impa7_mtd[i]);
iounmap((void *)impa7_map[i].virt);
impa7_map[i].virt = 0;
}
}
}
module_init(init_impa7);
module_exit(cleanup_impa7);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pavel Bartusek <pba@sysgo.de>");
MODULE_DESCRIPTION("MTD map driver for implementa impA7");

217
drivers/mtd/maps/integrator-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,217 @@
/*======================================================================
drivers/mtd/maps/integrator-flash.c: ARM Integrator flash map driver
Copyright (C) 2000 ARM Limited
Copyright (C) 2003 Deep Blue Solutions Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
This is access code for flashes using ARM's flash partitioning
standards.
$Id: integrator-flash.c,v 1.18 2004/11/01 13:26:15 rmk Exp $
======================================================================*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/mach/flash.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/system.h>
#ifdef CONFIG_ARCH_P720T
#define FLASH_BASE (0x04000000)
#define FLASH_SIZE (64*1024*1024)
#endif
struct armflash_info {
struct flash_platform_data *plat;
struct resource *res;
struct mtd_partition *parts;
struct mtd_info *mtd;
struct map_info map;
};
static void armflash_set_vpp(struct map_info *map, int on)
{
struct armflash_info *info = container_of(map, struct armflash_info, map);
if (info->plat && info->plat->set_vpp)
info->plat->set_vpp(on);
}
static const char *probes[] = { "cmdlinepart", "RedBoot", "afs", NULL };
static int armflash_probe(struct device *_dev)
{
struct platform_device *dev = to_platform_device(_dev);
struct flash_platform_data *plat = dev->dev.platform_data;
struct resource *res = dev->resource;
unsigned int size = res->end - res->start + 1;
struct armflash_info *info;
int err;
void __iomem *base;
info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL);
if (!info) {
err = -ENOMEM;
goto out;
}
memset(info, 0, sizeof(struct armflash_info));
info->plat = plat;
if (plat && plat->init) {
err = plat->init();
if (err)
goto no_resource;
}
info->res = request_mem_region(res->start, size, "armflash");
if (!info->res) {
err = -EBUSY;
goto no_resource;
}
base = ioremap(res->start, size);
if (!base) {
err = -ENOMEM;
goto no_mem;
}
/*
* look for CFI based flash parts fitted to this board
*/
info->map.size = size;
info->map.bankwidth = plat->width;
info->map.phys = res->start;
info->map.virt = base;
info->map.name = dev->dev.bus_id;
info->map.set_vpp = armflash_set_vpp;
simple_map_init(&info->map);
/*
* Also, the CFI layer automatically works out what size
* of chips we have, and does the necessary identification
* for us automatically.
*/
info->mtd = do_map_probe(plat->map_name, &info->map);
if (!info->mtd) {
err = -ENXIO;
goto no_device;
}
info->mtd->owner = THIS_MODULE;
err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0);
if (err > 0) {
err = add_mtd_partitions(info->mtd, info->parts, err);
if (err)
printk(KERN_ERR
"mtd partition registration failed: %d\n", err);
}
if (err == 0)
dev_set_drvdata(&dev->dev, info);
/*
* If we got an error, free all resources.
*/
if (err < 0) {
if (info->mtd) {
del_mtd_partitions(info->mtd);
map_destroy(info->mtd);
}
if (info->parts)
kfree(info->parts);
no_device:
iounmap(base);
no_mem:
release_mem_region(res->start, size);
no_resource:
if (plat && plat->exit)
plat->exit();
kfree(info);
}
out:
return err;
}
static int armflash_remove(struct device *_dev)
{
struct platform_device *dev = to_platform_device(_dev);
struct armflash_info *info = dev_get_drvdata(&dev->dev);
dev_set_drvdata(&dev->dev, NULL);
if (info) {
if (info->mtd) {
del_mtd_partitions(info->mtd);
map_destroy(info->mtd);
}
if (info->parts)
kfree(info->parts);
iounmap(info->map.virt);
release_resource(info->res);
kfree(info->res);
if (info->plat && info->plat->exit)
info->plat->exit();
kfree(info);
}
return 0;
}
static struct device_driver armflash_driver = {
.name = "armflash",
.bus = &platform_bus_type,
.probe = armflash_probe,
.remove = armflash_remove,
};
static int __init armflash_init(void)
{
return driver_register(&armflash_driver);
}
static void __exit armflash_exit(void)
{
driver_unregister(&armflash_driver);
}
module_init(armflash_init);
module_exit(armflash_exit);
MODULE_AUTHOR("ARM Ltd");
MODULE_DESCRIPTION("ARM Integrator CFI map driver");
MODULE_LICENSE("GPL");

464
drivers/mtd/maps/ipaq-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,464 @@
/*
* Flash memory access on iPAQ Handhelds (either SA1100 or PXA250 based)
*
* (C) 2000 Nicolas Pitre <nico@cam.org>
* (C) 2002 Hewlett-Packard Company <jamey.hicks@hp.com>
* (C) 2003 Christian Pellegrin <chri@ascensit.com>, <chri@infis.univ.ts.it>: concatenation of multiple flashes
*
* $Id: ipaq-flash.c,v 1.3 2004/11/04 13:24:15 gleixner Exp $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/page.h>
#include <asm/mach-types.h>
#include <asm/system.h>
#include <asm/errno.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#ifdef CONFIG_MTD_CONCAT
#include <linux/mtd/concat.h>
#endif
#include <asm/hardware.h>
#include <asm/arch-sa1100/h3600.h>
#include <asm/io.h>
#ifndef CONFIG_IPAQ_HANDHELD
#error This is for iPAQ Handhelds only
#endif
#ifdef CONFIG_SA1100_JORNADA56X
static void jornada56x_set_vpp(struct map_info *map, int vpp)
{
if (vpp)
GPSR = GPIO_GPIO26;
else
GPCR = GPIO_GPIO26;
GPDR |= GPIO_GPIO26;
}
#endif
#ifdef CONFIG_SA1100_JORNADA720
static void jornada720_set_vpp(struct map_info *map, int vpp)
{
if (vpp)
PPSR |= 0x80;
else
PPSR &= ~0x80;
PPDR |= 0x80;
}
#endif
#define MAX_IPAQ_CS 2 /* Number of CS we are going to test */
#define IPAQ_MAP_INIT(X) \
{ \
name: "IPAQ flash " X, \
}
static struct map_info ipaq_map[MAX_IPAQ_CS] = {
IPAQ_MAP_INIT("bank 1"),
IPAQ_MAP_INIT("bank 2")
};
static struct mtd_info *my_sub_mtd[MAX_IPAQ_CS] = {
NULL,
NULL
};
/*
* Here are partition information for all known IPAQ-based devices.
* See include/linux/mtd/partitions.h for definition of the mtd_partition
* structure.
*
* The *_max_flash_size is the maximum possible mapped flash size which
* is not necessarily the actual flash size. It must be no more than
* the value specified in the "struct map_desc *_io_desc" mapping
* definition for the corresponding machine.
*
* Please keep these in alphabetical order, and formatted as per existing
* entries. Thanks.
*/
#ifdef CONFIG_IPAQ_HANDHELD
static unsigned long h3xxx_max_flash_size = 0x04000000;
static struct mtd_partition h3xxx_partitions[] = {
{
name: "H3XXX boot firmware",
#ifndef CONFIG_LAB
size: 0x00040000,
#else
size: 0x00080000,
#endif
offset: 0,
#ifndef CONFIG_LAB
mask_flags: MTD_WRITEABLE, /* force read-only */
#endif
},
{
name: "H3XXX root jffs2",
#ifndef CONFIG_LAB
size: 0x2000000 - 2*0x40000, /* Warning, this is fixed later */
offset: 0x00040000,
#else
size: 0x2000000 - 0x40000 - 0x80000, /* Warning, this is fixed later */
offset: 0x00080000,
#endif
},
{
name: "asset",
size: 0x40000,
offset: 0x2000000 - 0x40000, /* Warning, this is fixed later */
mask_flags: MTD_WRITEABLE, /* force read-only */
}
};
#ifndef CONFIG_MTD_CONCAT
static struct mtd_partition h3xxx_partitions_bank2[] = {
/* this is used only on 2 CS machines when concat is not present */
{
name: "second H3XXX root jffs2",
size: 0x1000000 - 0x40000, /* Warning, this is fixed later */
offset: 0x00000000,
},
{
name: "second asset",
size: 0x40000,
offset: 0x1000000 - 0x40000, /* Warning, this is fixed later */
mask_flags: MTD_WRITEABLE, /* force read-only */
}
};
#endif
static DEFINE_SPINLOCK(ipaq_vpp_lock);
static void h3xxx_set_vpp(struct map_info *map, int vpp)
{
static int nest = 0;
spin_lock(&ipaq_vpp_lock);
if (vpp)
nest++;
else
nest--;
if (nest)
assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 1);
else
assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 0);
spin_unlock(&ipaq_vpp_lock);
}
#endif
#if defined(CONFIG_SA1100_JORNADA56X) || defined(CONFIG_SA1100_JORNADA720)
static unsigned long jornada_max_flash_size = 0x02000000;
static struct mtd_partition jornada_partitions[] = {
{
name: "Jornada boot firmware",
size: 0x00040000,
offset: 0,
mask_flags: MTD_WRITEABLE, /* force read-only */
}, {
name: "Jornada root jffs2",
size: MTDPART_SIZ_FULL,
offset: 0x00040000,
}
};
#endif
static struct mtd_partition *parsed_parts;
static struct mtd_info *mymtd;
static unsigned long cs_phys[] = {
#ifdef CONFIG_ARCH_SA1100
SA1100_CS0_PHYS,
SA1100_CS1_PHYS,
SA1100_CS2_PHYS,
SA1100_CS3_PHYS,
SA1100_CS4_PHYS,
SA1100_CS5_PHYS,
#else
PXA_CS0_PHYS,
PXA_CS1_PHYS,
PXA_CS2_PHYS,
PXA_CS3_PHYS,
PXA_CS4_PHYS,
PXA_CS5_PHYS,
#endif
};
static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
static int __init h1900_special_case(void);
int __init ipaq_mtd_init(void)
{
struct mtd_partition *parts = NULL;
int nb_parts = 0;
int parsed_nr_parts = 0;
const char *part_type;
int i; /* used when we have >1 flash chips */
unsigned long tot_flashsize = 0; /* used when we have >1 flash chips */
/* Default flash bankwidth */
// ipaq_map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
if (machine_is_h1900())
{
/* For our intents, the h1900 is not a real iPAQ, so we special-case it. */
return h1900_special_case();
}
if (machine_is_h3100() || machine_is_h1900())
for(i=0; i<MAX_IPAQ_CS; i++)
ipaq_map[i].bankwidth = 2;
else
for(i=0; i<MAX_IPAQ_CS; i++)
ipaq_map[i].bankwidth = 4;
/*
* Static partition definition selection
*/
part_type = "static";
simple_map_init(&ipaq_map[0]);
simple_map_init(&ipaq_map[1]);
#ifdef CONFIG_IPAQ_HANDHELD
if (machine_is_ipaq()) {
parts = h3xxx_partitions;
nb_parts = ARRAY_SIZE(h3xxx_partitions);
for(i=0; i<MAX_IPAQ_CS; i++) {
ipaq_map[i].size = h3xxx_max_flash_size;
ipaq_map[i].set_vpp = h3xxx_set_vpp;
ipaq_map[i].phys = cs_phys[i];
ipaq_map[i].virt = __ioremap(cs_phys[i], 0x04000000, 0, 1);
if (machine_is_h3100 () || machine_is_h1900())
ipaq_map[i].bankwidth = 2;
}
if (machine_is_h3600()) {
/* No asset partition here */
h3xxx_partitions[1].size += 0x40000;
nb_parts--;
}
}
#endif
#ifdef CONFIG_ARCH_H5400
if (machine_is_h5400()) {
ipaq_map[0].size = 0x02000000;
ipaq_map[1].size = 0x02000000;
ipaq_map[1].phys = 0x02000000;
ipaq_map[1].virt = ipaq_map[0].virt + 0x02000000;
}
#endif
#ifdef CONFIG_ARCH_H1900
if (machine_is_h1900()) {
ipaq_map[0].size = 0x00400000;
ipaq_map[1].size = 0x02000000;
ipaq_map[1].phys = 0x00080000;
ipaq_map[1].virt = ipaq_map[0].virt + 0x00080000;
}
#endif
#ifdef CONFIG_SA1100_JORNADA56X
if (machine_is_jornada56x()) {
parts = jornada_partitions;
nb_parts = ARRAY_SIZE(jornada_partitions);
ipaq_map[0].size = jornada_max_flash_size;
ipaq_map[0].set_vpp = jornada56x_set_vpp;
ipaq_map[0].virt = (__u32)__ioremap(0x0, 0x04000000, 0, 1);
}
#endif
#ifdef CONFIG_SA1100_JORNADA720
if (machine_is_jornada720()) {
parts = jornada_partitions;
nb_parts = ARRAY_SIZE(jornada_partitions);
ipaq_map[0].size = jornada_max_flash_size;
ipaq_map[0].set_vpp = jornada720_set_vpp;
}
#endif
if (machine_is_ipaq()) { /* for iPAQs only */
for(i=0; i<MAX_IPAQ_CS; i++) {
printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with CFI.\n", ipaq_map[i].bankwidth*8, ipaq_map[i].virt);
my_sub_mtd[i] = do_map_probe("cfi_probe", &ipaq_map[i]);
if (!my_sub_mtd[i]) {
printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with JEDEC.\n", ipaq_map[i].bankwidth*8, ipaq_map[i].virt);
my_sub_mtd[i] = do_map_probe("jedec_probe", &ipaq_map[i]);
}
if (!my_sub_mtd[i]) {
printk(KERN_NOTICE "iPAQ flash: failed to find flash.\n");
if (i)
break;
else
return -ENXIO;
} else
printk(KERN_NOTICE "iPAQ flash: found %d bytes\n", my_sub_mtd[i]->size);
/* do we really need this debugging? --joshua 20030703 */
// printk("my_sub_mtd[%d]=%p\n", i, my_sub_mtd[i]);
my_sub_mtd[i]->owner = THIS_MODULE;
tot_flashsize += my_sub_mtd[i]->size;
}
#ifdef CONFIG_MTD_CONCAT
/* fix the asset location */
# ifdef CONFIG_LAB
h3xxx_partitions[1].size = tot_flashsize - 0x40000 - 0x80000 /* extra big boot block */;
# else
h3xxx_partitions[1].size = tot_flashsize - 2 * 0x40000;
# endif
h3xxx_partitions[2].offset = tot_flashsize - 0x40000;
/* and concat the devices */
mymtd = mtd_concat_create(&my_sub_mtd[0], i,
"ipaq");
if (!mymtd) {
printk("Cannot create iPAQ concat device\n");
return -ENXIO;
}
#else
mymtd = my_sub_mtd[0];
/*
*In the very near future, command line partition parsing
* will use the device name as 'mtd-id' instead of a value
* passed to the parse_cmdline_partitions() routine. Since
* the bootldr says 'ipaq', make sure it continues to work.
*/
mymtd->name = "ipaq";
if ((machine_is_h3600())) {
# ifdef CONFIG_LAB
h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x80000;
# else
h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000;
# endif
nb_parts = 2;
} else {
# ifdef CONFIG_LAB
h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000 - 0x80000; /* extra big boot block */
# else
h3xxx_partitions[1].size = my_sub_mtd[0]->size - 2*0x40000;
# endif
h3xxx_partitions[2].offset = my_sub_mtd[0]->size - 0x40000;
}
if (my_sub_mtd[1]) {
# ifdef CONFIG_LAB
h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x80000;
# else
h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x40000;
# endif
h3xxx_partitions_bank2[1].offset = my_sub_mtd[1]->size - 0x40000;
}
#endif
}
else {
/*
* Now let's probe for the actual flash. Do it here since
* specific machine settings might have been set above.
*/
printk(KERN_NOTICE "IPAQ flash: probing %d-bit flash bus, window=%lx\n", ipaq_map[0].bankwidth*8, ipaq_map[0].virt);
mymtd = do_map_probe("cfi_probe", &ipaq_map[0]);
if (!mymtd)
return -ENXIO;
mymtd->owner = THIS_MODULE;
}
/*
* Dynamic partition selection stuff (might override the static ones)
*/
i = parse_mtd_partitions(mymtd, part_probes, &parsed_parts, 0);
if (i > 0) {
nb_parts = parsed_nr_parts = i;
parts = parsed_parts;
part_type = "dynamic";
}
if (!parts) {
printk(KERN_NOTICE "IPAQ flash: no partition info available, registering whole flash at once\n");
add_mtd_device(mymtd);
#ifndef CONFIG_MTD_CONCAT
if (my_sub_mtd[1])
add_mtd_device(my_sub_mtd[1]);
#endif
} else {
printk(KERN_NOTICE "Using %s partition definition\n", part_type);
add_mtd_partitions(mymtd, parts, nb_parts);
#ifndef CONFIG_MTD_CONCAT
if (my_sub_mtd[1])
add_mtd_partitions(my_sub_mtd[1], h3xxx_partitions_bank2, ARRAY_SIZE(h3xxx_partitions_bank2));
#endif
}
return 0;
}
static void __exit ipaq_mtd_cleanup(void)
{
int i;
if (mymtd) {
del_mtd_partitions(mymtd);
#ifndef CONFIG_MTD_CONCAT
if (my_sub_mtd[1])
del_mtd_partitions(my_sub_mtd[1]);
#endif
map_destroy(mymtd);
#ifdef CONFIG_MTD_CONCAT
for(i=0; i<MAX_IPAQ_CS; i++)
#else
for(i=1; i<MAX_IPAQ_CS; i++)
#endif
{
if (my_sub_mtd[i])
map_destroy(my_sub_mtd[i]);
}
if (parsed_parts)
kfree(parsed_parts);
}
}
static int __init h1900_special_case(void)
{
/* The iPAQ h1900 is a special case - it has weird ROM. */
simple_map_init(&ipaq_map[0]);
ipaq_map[0].size = 0x80000;
ipaq_map[0].set_vpp = h3xxx_set_vpp;
ipaq_map[0].phys = 0x0;
ipaq_map[0].virt = __ioremap(0x0, 0x04000000, 0, 1);
ipaq_map[0].bankwidth = 2;
printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with JEDEC.\n", ipaq_map[0].bankwidth*8, ipaq_map[0].virt);
mymtd = do_map_probe("jedec_probe", &ipaq_map[0]);
if (!mymtd)
return -ENODEV;
add_mtd_device(mymtd);
printk(KERN_NOTICE "iPAQ flash: registered h1910 flash\n");
return 0;
}
module_init(ipaq_mtd_init);
module_exit(ipaq_mtd_cleanup);
MODULE_AUTHOR("Jamey Hicks");
MODULE_DESCRIPTION("IPAQ CFI map driver");
MODULE_LICENSE("MIT");

119
drivers/mtd/maps/iq80310.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,119 @@
/*
* $Id: iq80310.c,v 1.20 2004/11/04 13:24:15 gleixner Exp $
*
* Mapping for the Intel XScale IQ80310 evaluation board
*
* Author: Nicolas Pitre
* Copyright: (C) 2001 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#define WINDOW_ADDR 0
#define WINDOW_SIZE 8*1024*1024
#define BUSWIDTH 1
static struct mtd_info *mymtd;
static struct map_info iq80310_map = {
.name = "IQ80310 flash",
.size = WINDOW_SIZE,
.bankwidth = BUSWIDTH,
.phys = WINDOW_ADDR
};
static struct mtd_partition iq80310_partitions[4] = {
{
.name = "Firmware",
.size = 0x00080000,
.offset = 0,
.mask_flags = MTD_WRITEABLE /* force read-only */
},{
.name = "Kernel",
.size = 0x000a0000,
.offset = 0x00080000,
},{
.name = "Filesystem",
.size = 0x00600000,
.offset = 0x00120000
},{
.name = "RedBoot",
.size = 0x000e0000,
.offset = 0x00720000,
.mask_flags = MTD_WRITEABLE
}
};
static struct mtd_info *mymtd;
static struct mtd_partition *parsed_parts;
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
static int __init init_iq80310(void)
{
struct mtd_partition *parts;
int nb_parts = 0;
int parsed_nr_parts = 0;
int ret;
iq80310_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!iq80310_map.virt) {
printk("Failed to ioremap\n");
return -EIO;
}
simple_map_init(&iq80310_map);
mymtd = do_map_probe("cfi_probe", &iq80310_map);
if (!mymtd) {
iounmap((void *)iq80310_map.virt);
return -ENXIO;
}
mymtd->owner = THIS_MODULE;
ret = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);
if (ret > 0)
parsed_nr_parts = ret;
if (parsed_nr_parts > 0) {
parts = parsed_parts;
nb_parts = parsed_nr_parts;
} else {
parts = iq80310_partitions;
nb_parts = ARRAY_SIZE(iq80310_partitions);
}
add_mtd_partitions(mymtd, parts, nb_parts);
return 0;
}
static void __exit cleanup_iq80310(void)
{
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
if (parsed_parts)
kfree(parsed_parts);
}
if (iq80310_map.virt)
iounmap((void *)iq80310_map.virt);
}
module_init(init_iq80310);
module_exit(cleanup_iq80310);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
MODULE_DESCRIPTION("MTD map driver for Intel XScale IQ80310 evaluation board");

280
drivers/mtd/maps/ixp2000.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,280 @@
/*
* $Id: ixp2000.c,v 1.5 2004/11/16 17:15:48 dsaxena Exp $
*
* drivers/mtd/maps/ixp2000.c
*
* Mapping for the Intel XScale IXP2000 based systems
*
* Copyright (C) 2002 Intel Corp.
* Copyright (C) 2003-2004 MontaVista Software, Inc.
*
* Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
* Maintainer: Deepak Saxena <dsaxena@plexity.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/flash.h>
#include <linux/reboot.h>
struct ixp2000_flash_info {
struct mtd_info *mtd;
struct map_info map;
struct mtd_partition *partitions;
struct resource *res;
int nr_banks;
};
static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
{
unsigned long (*set_bank)(unsigned long) =
(unsigned long(*)(unsigned long))map->map_priv_2;
return (set_bank ? set_bank(ofs) : ofs);
}
#ifdef __ARMEB__
/*
* Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which
* causes the lower address bits to be XORed with 0x11 on 8 bit accesses
* and XORed with 0x10 on 16 bit accesses. See the spec update, erratum 44.
*/
static int erratum44_workaround = 0;
static inline unsigned long address_fix8_write(unsigned long addr)
{
if (erratum44_workaround) {
return (addr ^ 3);
}
return addr;
}
#else
#define address_fix8_write(x) (x)
#endif
static map_word ixp2000_flash_read8(struct map_info *map, unsigned long ofs)
{
map_word val;
val.x[0] = *((u8 *)(map->map_priv_1 + flash_bank_setup(map, ofs)));
return val;
}
/*
* We can't use the standard memcpy due to the broken SlowPort
* address translation on rev A0 and A1 silicon and the fact that
* we have banked flash.
*/
static void ixp2000_flash_copy_from(struct map_info *map, void *to,
unsigned long from, ssize_t len)
{
from = flash_bank_setup(map, from);
while(len--)
*(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++);
}
static void ixp2000_flash_write8(struct map_info *map, map_word d, unsigned long ofs)
{
*(__u8 *) (address_fix8_write(map->map_priv_1 +
flash_bank_setup(map, ofs))) = d.x[0];
}
static void ixp2000_flash_copy_to(struct map_info *map, unsigned long to,
const void *from, ssize_t len)
{
to = flash_bank_setup(map, to);
while(len--) {
unsigned long tmp = address_fix8_write(map->map_priv_1 + to++);
*(__u8 *)(tmp) = *(__u8 *)(from++);
}
}
static int ixp2000_flash_remove(struct device *_dev)
{
struct platform_device *dev = to_platform_device(_dev);
struct flash_platform_data *plat = dev->dev.platform_data;
struct ixp2000_flash_info *info = dev_get_drvdata(&dev->dev);
dev_set_drvdata(&dev->dev, NULL);
if(!info)
return 0;
if (info->mtd) {
del_mtd_partitions(info->mtd);
map_destroy(info->mtd);
}
if (info->map.map_priv_1)
iounmap((void *) info->map.map_priv_1);
if (info->partitions) {
kfree(info->partitions); }
if (info->res) {
release_resource(info->res);
kfree(info->res);
}
if (plat->exit)
plat->exit();
return 0;
}
static int ixp2000_flash_probe(struct device *_dev)
{
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
struct platform_device *dev = to_platform_device(_dev);
struct ixp2000_flash_data *ixp_data = dev->dev.platform_data;
struct flash_platform_data *plat;
struct ixp2000_flash_info *info;
unsigned long window_size;
int err = -1;
if (!ixp_data)
return -ENODEV;
plat = ixp_data->platform_data;
if (!plat)
return -ENODEV;
window_size = dev->resource->end - dev->resource->start + 1;
dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n",
ixp_data->nr_banks, ((u32)window_size >> 20));
if (plat->width != 1) {
dev_err(_dev, "IXP2000 MTD map only supports 8-bit mode, asking for %d\n",
plat->width * 8);
return -EIO;
}
info = kmalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL);
if(!info) {
err = -ENOMEM;
goto Error;
}
memzero(info, sizeof(struct ixp2000_flash_info));
dev_set_drvdata(&dev->dev, info);
/*
* Tell the MTD layer we're not 1:1 mapped so that it does
* not attempt to do a direct access on us.
*/
info->map.phys = NO_XIP;
info->nr_banks = ixp_data->nr_banks;
info->map.size = ixp_data->nr_banks * window_size;
info->map.bankwidth = 1;
/*
* map_priv_2 is used to store a ptr to to the bank_setup routine
*/
info->map.map_priv_2 = (void __iomem *) ixp_data->bank_setup;
info->map.name = dev->dev.bus_id;
info->map.read = ixp2000_flash_read8;
info->map.write = ixp2000_flash_write8;
info->map.copy_from = ixp2000_flash_copy_from;
info->map.copy_to = ixp2000_flash_copy_to;
info->res = request_mem_region(dev->resource->start,
dev->resource->end - dev->resource->start + 1,
dev->dev.bus_id);
if (!info->res) {
dev_err(_dev, "Could not reserve memory region\n");
err = -ENOMEM;
goto Error;
}
info->map.map_priv_1 = ioremap(dev->resource->start,
dev->resource->end - dev->resource->start + 1);
if (!info->map.map_priv_1) {
dev_err(_dev, "Failed to ioremap flash region\n");
err = -EIO;
goto Error;
}
/*
* Setup read mode for FLASH
*/
*IXP2000_SLOWPORT_FRM = 1;
#if defined(__ARMEB__)
/*
* Enable erratum 44 workaround for NPUs with broken slowport
*/
erratum44_workaround = ixp2000_has_broken_slowport();
dev_info(_dev, "Erratum 44 workaround %s\n",
erratum44_workaround ? "enabled" : "disabled");
#endif
info->mtd = do_map_probe(plat->map_name, &info->map);
if (!info->mtd) {
dev_err(_dev, "map_probe failed\n");
err = -ENXIO;
goto Error;
}
info->mtd->owner = THIS_MODULE;
err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
if (err > 0) {
err = add_mtd_partitions(info->mtd, info->partitions, err);
if(err)
dev_err(_dev, "Could not parse partitions\n");
}
if (err)
goto Error;
return 0;
Error:
ixp2000_flash_remove(_dev);
return err;
}
static struct device_driver ixp2000_flash_driver = {
.name = "IXP2000-Flash",
.bus = &platform_bus_type,
.probe = &ixp2000_flash_probe,
.remove = &ixp2000_flash_remove
};
static int __init ixp2000_flash_init(void)
{
return driver_register(&ixp2000_flash_driver);
}
static void __exit ixp2000_flash_exit(void)
{
driver_unregister(&ixp2000_flash_driver);
}
module_init(ixp2000_flash_init);
module_exit(ixp2000_flash_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");

259
drivers/mtd/maps/ixp4xx.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,259 @@
/*
* $Id: ixp4xx.c,v 1.7 2004/11/04 13:24:15 gleixner Exp $
*
* drivers/mtd/maps/ixp4xx.c
*
* MTD Map file for IXP4XX based systems. Please do not make per-board
* changes in here. If your board needs special setup, do it in your
* platform level code in arch/arm/mach-ixp4xx/board-setup.c
*
* Original Author: Intel Corporation
* Maintainer: Deepak Saxena <dsaxena@mvista.com>
*
* Copyright (C) 2002 Intel Corporation
* Copyright (C) 2003-2004 MontaVista Software, Inc.
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/mach/flash.h>
#include <linux/reboot.h>
#ifndef __ARMEB__
#define BYTE0(h) ((h) & 0xFF)
#define BYTE1(h) (((h) >> 8) & 0xFF)
#else
#define BYTE0(h) (((h) >> 8) & 0xFF)
#define BYTE1(h) ((h) & 0xFF)
#endif
static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
{
map_word val;
val.x[0] = *(__u16 *) (map->map_priv_1 + ofs);
return val;
}
/*
* The IXP4xx expansion bus only allows 16-bit wide acceses
* when attached to a 16-bit wide device (such as the 28F128J3A),
* so we can't just memcpy_fromio().
*/
static void ixp4xx_copy_from(struct map_info *map, void *to,
unsigned long from, ssize_t len)
{
int i;
u8 *dest = (u8 *) to;
u16 *src = (u16 *) (map->map_priv_1 + from);
u16 data;
for (i = 0; i < (len / 2); i++) {
data = src[i];
dest[i * 2] = BYTE0(data);
dest[i * 2 + 1] = BYTE1(data);
}
if (len & 1)
dest[len - 1] = BYTE0(src[i]);
}
/*
* Unaligned writes are ignored, causing the 8-bit
* probe to fail and proceed to the 16-bit probe (which succeeds).
*/
static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
{
if (!(adr & 1))
*(__u16 *) (map->map_priv_1 + adr) = d.x[0];
}
/*
* Fast write16 function without the probing check above
*/
static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
{
*(__u16 *) (map->map_priv_1 + adr) = d.x[0];
}
struct ixp4xx_flash_info {
struct mtd_info *mtd;
struct map_info map;
struct mtd_partition *partitions;
struct resource *res;
};
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
static int ixp4xx_flash_remove(struct device *_dev)
{
struct platform_device *dev = to_platform_device(_dev);
struct flash_platform_data *plat = dev->dev.platform_data;
struct ixp4xx_flash_info *info = dev_get_drvdata(&dev->dev);
map_word d;
dev_set_drvdata(&dev->dev, NULL);
if(!info)
return 0;
/*
* This is required for a soft reboot to work.
*/
d.x[0] = 0xff;
ixp4xx_write16(&info->map, d, 0x55 * 0x2);
if (info->mtd) {
del_mtd_partitions(info->mtd);
map_destroy(info->mtd);
}
if (info->map.map_priv_1)
iounmap((void *) info->map.map_priv_1);
if (info->partitions)
kfree(info->partitions);
if (info->res) {
release_resource(info->res);
kfree(info->res);
}
if (plat->exit)
plat->exit();
/* Disable flash write */
*IXP4XX_EXP_CS0 &= ~IXP4XX_FLASH_WRITABLE;
return 0;
}
static int ixp4xx_flash_probe(struct device *_dev)
{
struct platform_device *dev = to_platform_device(_dev);
struct flash_platform_data *plat = dev->dev.platform_data;
struct ixp4xx_flash_info *info;
int err = -1;
if (!plat)
return -ENODEV;
if (plat->init) {
err = plat->init();
if (err)
return err;
}
info = kmalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL);
if(!info) {
err = -ENOMEM;
goto Error;
}
memzero(info, sizeof(struct ixp4xx_flash_info));
dev_set_drvdata(&dev->dev, info);
/*
* Enable flash write
* TODO: Move this out to board specific code
*/
*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
/*
* Tell the MTD layer we're not 1:1 mapped so that it does
* not attempt to do a direct access on us.
*/
info->map.phys = NO_XIP;
info->map.size = dev->resource->end - dev->resource->start + 1;
/*
* We only support 16-bit accesses for now. If and when
* any board use 8-bit access, we'll fixup the driver to
* handle that.
*/
info->map.bankwidth = 2;
info->map.name = dev->dev.bus_id;
info->map.read = ixp4xx_read16,
info->map.write = ixp4xx_probe_write16,
info->map.copy_from = ixp4xx_copy_from,
info->res = request_mem_region(dev->resource->start,
dev->resource->end - dev->resource->start + 1,
"IXP4XXFlash");
if (!info->res) {
printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n");
err = -ENOMEM;
goto Error;
}
info->map.map_priv_1 = ioremap(dev->resource->start,
dev->resource->end - dev->resource->start + 1);
if (!info->map.map_priv_1) {
printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n");
err = -EIO;
goto Error;
}
info->mtd = do_map_probe(plat->map_name, &info->map);
if (!info->mtd) {
printk(KERN_ERR "IXP4XXFlash: map_probe failed\n");
err = -ENXIO;
goto Error;
}
info->mtd->owner = THIS_MODULE;
/* Use the fast version */
info->map.write = ixp4xx_write16,
err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
if (err > 0) {
err = add_mtd_partitions(info->mtd, info->partitions, err);
if(err)
printk(KERN_ERR "Could not parse partitions\n");
}
if (err)
goto Error;
return 0;
Error:
ixp4xx_flash_remove(_dev);
return err;
}
static struct device_driver ixp4xx_flash_driver = {
.name = "IXP4XX-Flash",
.bus = &platform_bus_type,
.probe = ixp4xx_flash_probe,
.remove = ixp4xx_flash_remove,
};
static int __init ixp4xx_flash_init(void)
{
return driver_register(&ixp4xx_flash_driver);
}
static void __exit ixp4xx_flash_exit(void)
{
driver_unregister(&ixp4xx_flash_driver);
}
module_init(ixp4xx_flash_init);
module_exit(ixp4xx_flash_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems")
MODULE_AUTHOR("Deepak Saxena");

157
drivers/mtd/maps/l440gx.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,157 @@
/*
* $Id: l440gx.c,v 1.17 2004/11/28 09:40:39 dwmw2 Exp $
*
* BIOS Flash chip on Intel 440GX board.
*
* Bugs this currently does not work under linuxBIOS.
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/config.h>
#define PIIXE_IOBASE_RESOURCE 11
#define WINDOW_ADDR 0xfff00000
#define WINDOW_SIZE 0x00100000
#define BUSWIDTH 1
static u32 iobase;
#define IOBASE iobase
#define TRIBUF_PORT (IOBASE+0x37)
#define VPP_PORT (IOBASE+0x28)
static struct mtd_info *mymtd;
/* Is this really the vpp port? */
static void l440gx_set_vpp(struct map_info *map, int vpp)
{
unsigned long l;
l = inl(VPP_PORT);
if (vpp) {
l |= 1;
} else {
l &= ~1;
}
outl(l, VPP_PORT);
}
static struct map_info l440gx_map = {
.name = "L440GX BIOS",
.size = WINDOW_SIZE,
.bankwidth = BUSWIDTH,
.phys = WINDOW_ADDR,
#if 0
/* FIXME verify that this is the
* appripriate code for vpp enable/disable
*/
.set_vpp = l440gx_set_vpp
#endif
};
static int __init init_l440gx(void)
{
struct pci_dev *dev, *pm_dev;
struct resource *pm_iobase;
__u16 word;
dev = pci_find_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB_0, NULL);
pm_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
if (!dev || !pm_dev) {
printk(KERN_NOTICE "L440GX flash mapping: failed to find PIIX4 ISA bridge, cannot continue\n");
return -ENODEV;
}
l440gx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
if (!l440gx_map.virt) {
printk(KERN_WARNING "Failed to ioremap L440GX flash region\n");
return -ENOMEM;
}
simple_map_init(&l440gx_map);
printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.virt);
/* Setup the pm iobase resource
* This code should move into some kind of generic bridge
* driver but for the moment I'm content with getting the
* allocation correct.
*/
pm_iobase = &pm_dev->resource[PIIXE_IOBASE_RESOURCE];
if (!(pm_iobase->flags & IORESOURCE_IO)) {
pm_iobase->name = "pm iobase";
pm_iobase->start = 0;
pm_iobase->end = 63;
pm_iobase->flags = IORESOURCE_IO;
/* Put the current value in the resource */
pci_read_config_dword(pm_dev, 0x40, &iobase);
iobase &= ~1;
pm_iobase->start += iobase & ~1;
pm_iobase->end += iobase & ~1;
/* Allocate the resource region */
if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) {
printk(KERN_WARNING "Could not allocate pm iobase resource\n");
iounmap(l440gx_map.virt);
return -ENXIO;
}
}
/* Set the iobase */
iobase = pm_iobase->start;
pci_write_config_dword(pm_dev, 0x40, iobase | 1);
/* Set XBCS# */
pci_read_config_word(dev, 0x4e, &word);
word |= 0x4;
pci_write_config_word(dev, 0x4e, word);
/* Supply write voltage to the chip */
l440gx_set_vpp(&l440gx_map, 1);
/* Enable the gate on the WE line */
outb(inb(TRIBUF_PORT) & ~1, TRIBUF_PORT);
printk(KERN_NOTICE "Enabled WE line to L440GX BIOS flash chip.\n");
mymtd = do_map_probe("jedec_probe", &l440gx_map);
if (!mymtd) {
printk(KERN_NOTICE "JEDEC probe on BIOS chip failed. Using ROM\n");
mymtd = do_map_probe("map_rom", &l440gx_map);
}
if (mymtd) {
mymtd->owner = THIS_MODULE;
add_mtd_device(mymtd);
return 0;
}
iounmap(l440gx_map.virt);
return -ENXIO;
}
static void __exit cleanup_l440gx(void)
{
del_mtd_device(mymtd);
map_destroy(mymtd);
iounmap(l440gx_map.virt);
}
module_init(init_l440gx);
module_exit(cleanup_l440gx);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("MTD map driver for BIOS chips on Intel L440GX motherboards");

102
drivers/mtd/maps/lasat.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,102 @@
/*
* Flash device on Lasat 100 and 200 boards
*
* (C) 2002 Brian Murphy <brian@murphy.dk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* $Id: lasat.c,v 1.9 2004/11/04 13:24:15 gleixner Exp $
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/config.h>
#include <asm/lasat/lasat.h>
static struct mtd_info *lasat_mtd;
static struct mtd_partition partition_info[LASAT_MTD_LAST];
static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
static void lasat_set_vpp(struct map_info *map, int vpp)
{
if (vpp)
*lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
else
*lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit);
}
static struct map_info lasat_map = {
.name = "LASAT flash",
.bankwidth = 4,
.set_vpp = lasat_set_vpp
};
static int __init init_lasat(void)
{
int i;
/* since we use AMD chips and set_vpp is not implimented
* for these (yet) we still have to permanently enable flash write */
printk(KERN_NOTICE "Unprotecting flash\n");
ENABLE_VPP((&lasat_map));
lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
lasat_map.virt = ioremap_nocache(
lasat_map.phys, lasat_board_info.li_flash_size);
lasat_map.size = lasat_board_info.li_flash_size;
simple_map_init(&lasat_map);
for (i=0; i < LASAT_MTD_LAST; i++)
partition_info[i].name = lasat_mtd_partnames[i];
lasat_mtd = do_map_probe("cfi_probe", &lasat_map);
if (!lasat_mtd)
lasat_mtd = do_map_probe("jedec_probe", &lasat_map);
if (lasat_mtd) {
u32 size, offset = 0;
lasat_mtd->owner = THIS_MODULE;
for (i=0; i < LASAT_MTD_LAST; i++) {
size = lasat_flash_partition_size(i);
partition_info[i].size = size;
partition_info[i].offset = offset;
offset += size;
}
add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST );
return 0;
}
return -ENXIO;
}
static void __exit cleanup_lasat(void)
{
if (lasat_mtd) {
del_mtd_partitions(lasat_mtd);
map_destroy(lasat_mtd);
}
if (lasat_map.virt) {
lasat_map.virt = 0;
}
}
module_init(init_lasat);
module_exit(cleanup_lasat);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Brian Murphy <brian@murphy.dk>");
MODULE_DESCRIPTION("Lasat Safepipe/Masquerade MTD map driver");

168
drivers/mtd/maps/lubbock-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,168 @@
/*
* $Id: lubbock-flash.c,v 1.19 2004/11/04 13:24:15 gleixner Exp $
*
* Map driver for the Lubbock developer platform.
*
* Author: Nicolas Pitre
* Copyright: (C) 2001 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/lubbock.h>
#define ROM_ADDR 0x00000000
#define FLASH_ADDR 0x04000000
#define WINDOW_SIZE 64*1024*1024
static void lubbock_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len)
{
consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
}
static struct map_info lubbock_maps[2] = { {
.size = WINDOW_SIZE,
.phys = 0x00000000,
.inval_cache = lubbock_map_inval_cache,
}, {
.size = WINDOW_SIZE,
.phys = 0x04000000,
.inval_cache = lubbock_map_inval_cache,
} };
static struct mtd_partition lubbock_partitions[] = {
{
.name = "Bootloader",
.size = 0x00040000,
.offset = 0,
.mask_flags = MTD_WRITEABLE /* force read-only */
},{
.name = "Kernel",
.size = 0x00100000,
.offset = 0x00040000,
},{
.name = "Filesystem",
.size = MTDPART_SIZ_FULL,
.offset = 0x00140000
}
};
static struct mtd_info *mymtds[2];
static struct mtd_partition *parsed_parts[2];
static int nr_parsed_parts[2];
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
static int __init init_lubbock(void)
{
int flashboot = (LUB_CONF_SWITCHES & 1);
int ret = 0, i;
lubbock_maps[0].bankwidth = lubbock_maps[1].bankwidth =
(BOOT_DEF & 1) ? 2 : 4;
/* Compensate for the nROMBT switch which swaps the flash banks */
printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n",
flashboot?"Flash":"ROM", flashboot);
lubbock_maps[flashboot^1].name = "Lubbock Application Flash";
lubbock_maps[flashboot].name = "Lubbock Boot ROM";
for (i = 0; i < 2; i++) {
lubbock_maps[i].virt = ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
if (!lubbock_maps[i].virt) {
printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name);
if (!ret)
ret = -ENOMEM;
continue;
}
lubbock_maps[i].cached = ioremap_cached(lubbock_maps[i].phys, WINDOW_SIZE);
if (!lubbock_maps[i].cached)
printk(KERN_WARNING "Failed to ioremap cached %s\n", lubbock_maps[i].name);
simple_map_init(&lubbock_maps[i]);
printk(KERN_NOTICE "Probing %s at physical address 0x%08lx (%d-bit bankwidth)\n",
lubbock_maps[i].name, lubbock_maps[i].phys,
lubbock_maps[i].bankwidth * 8);
mymtds[i] = do_map_probe("cfi_probe", &lubbock_maps[i]);
if (!mymtds[i]) {
iounmap((void *)lubbock_maps[i].virt);
if (lubbock_maps[i].cached)
iounmap(lubbock_maps[i].cached);
if (!ret)
ret = -EIO;
continue;
}
mymtds[i]->owner = THIS_MODULE;
ret = parse_mtd_partitions(mymtds[i], probes,
&parsed_parts[i], 0);
if (ret > 0)
nr_parsed_parts[i] = ret;
}
if (!mymtds[0] && !mymtds[1])
return ret;
for (i = 0; i < 2; i++) {
if (!mymtds[i]) {
printk(KERN_WARNING "%s is absent. Skipping\n", lubbock_maps[i].name);
} else if (nr_parsed_parts[i]) {
add_mtd_partitions(mymtds[i], parsed_parts[i], nr_parsed_parts[i]);
} else if (!i) {
printk("Using static partitions on %s\n", lubbock_maps[i].name);
add_mtd_partitions(mymtds[i], lubbock_partitions, ARRAY_SIZE(lubbock_partitions));
} else {
printk("Registering %s as whole device\n", lubbock_maps[i].name);
add_mtd_device(mymtds[i]);
}
}
return 0;
}
static void __exit cleanup_lubbock(void)
{
int i;
for (i = 0; i < 2; i++) {
if (!mymtds[i])
continue;
if (nr_parsed_parts[i] || !i)
del_mtd_partitions(mymtds[i]);
else
del_mtd_device(mymtds[i]);
map_destroy(mymtds[i]);
iounmap((void *)lubbock_maps[i].virt);
if (lubbock_maps[i].cached)
iounmap(lubbock_maps[i].cached);
if (parsed_parts[i])
kfree(parsed_parts[i]);
}
}
module_init(init_lubbock);
module_exit(cleanup_lubbock);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
MODULE_DESCRIPTION("MTD map driver for Intel Lubbock");

44
drivers/mtd/maps/map_funcs.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,44 @@
/*
* $Id: map_funcs.c,v 1.9 2004/07/13 22:33:15 dwmw2 Exp $
*
* Out-of-line map I/O functions for simple maps when CONFIG_COMPLEX_MAPPINGS
* is enabled.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/map.h>
static map_word simple_map_read(struct map_info *map, unsigned long ofs)
{
return inline_map_read(map, ofs);
}
static void simple_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
{
inline_map_write(map, datum, ofs);
}
static void simple_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
inline_map_copy_from(map, to, from, len);
}
static void simple_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
inline_map_copy_to(map, to, from, len);
}
void simple_map_init(struct map_info *map)
{
BUG_ON(!map_bankwidth_supported(map->bankwidth));
map->read = simple_map_read;
map->write = simple_map_write;
map->copy_from = simple_map_copy_from;
map->copy_to = simple_map_copy_to;
}
EXPORT_SYMBOL(simple_map_init);
MODULE_LICENSE("GPL");

100
drivers/mtd/maps/mbx860.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,100 @@
/*
* $Id: mbx860.c,v 1.8 2004/11/04 13:24:15 gleixner Exp $
*
* Handle mapping of the flash on MBX860 boards
*
* Author: Anton Todorov
* Copyright: (C) 2001 Emness Technology
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#define WINDOW_ADDR 0xfe000000
#define WINDOW_SIZE 0x00200000
/* Flash / Partition sizing */
#define MAX_SIZE_KiB 8192
#define BOOT_PARTITION_SIZE_KiB 512
#define KERNEL_PARTITION_SIZE_KiB 5632
#define APP_PARTITION_SIZE_KiB 2048
#define NUM_PARTITIONS 3
/* partition_info gives details on the logical partitions that the split the
* single flash device into. If the size if zero we use up to the end of the
* device. */
static struct mtd_partition partition_info[]={
{ .name = "MBX flash BOOT partition",
.offset = 0,
.size = BOOT_PARTITION_SIZE_KiB*1024 },
{ .name = "MBX flash DATA partition",
.offset = BOOT_PARTITION_SIZE_KiB*1024,
.size = (KERNEL_PARTITION_SIZE_KiB)*1024 },
{ .name = "MBX flash APPLICATION partition",
.offset = (BOOT_PARTITION_SIZE_KiB+KERNEL_PARTITION_SIZE_KiB)*1024 }
};
static struct mtd_info *mymtd;
struct map_info mbx_map = {
.name = "MBX flash",
.size = WINDOW_SIZE,
.phys = WINDOW_ADDR,
.bankwidth = 4,
};
int __init init_mbx(void)
{
printk(KERN_NOTICE "Motorola MBX flash device: 0x%x at 0x%x\n", WINDOW_SIZE*4, WINDOW_ADDR);
mbx_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
if (!mbx_map.virt) {
printk("Failed to ioremap\n");
return -EIO;
}
simple_map_init(&mbx_map);
mymtd = do_map_probe("jedec_probe", &mbx_map);
if (mymtd) {
mymtd->owner = THIS_MODULE;
add_mtd_device(mymtd);
add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
return 0;
}
iounmap((void *)mbx_map.virt);
return -ENXIO;
}
static void __exit cleanup_mbx(void)
{
if (mymtd) {
del_mtd_device(mymtd);
map_destroy(mymtd);
}
if (mbx_map.virt) {
iounmap((void *)mbx_map.virt);
mbx_map.virt = 0;
}
}
module_init(init_mbx);
module_exit(cleanup_mbx);
MODULE_AUTHOR("Anton Todorov <a.todorov@emness.com>");
MODULE_DESCRIPTION("MTD map driver for Motorola MBX860 board");
MODULE_LICENSE("GPL");

81
drivers/mtd/maps/mpc1211.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,81 @@
/*
* Flash on MPC-1211
*
* $Id: mpc1211.c,v 1.4 2004/09/16 23:27:13 gleixner Exp $
*
* (C) 2002 Interface, Saito.K & Jeanne
*
* GPL'd
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/config.h>
static struct mtd_info *flash_mtd;
static struct mtd_partition *parsed_parts;
struct map_info mpc1211_flash_map = {
.name = "MPC-1211 FLASH",
.size = 0x80000,
.bankwidth = 1,
};
static struct mtd_partition mpc1211_partitions[] = {
{
.name = "IPL & ETH-BOOT",
.offset = 0x00000000,
.size = 0x10000,
},
{
.name = "Flash FS",
.offset = 0x00010000,
.size = MTDPART_SIZ_FULL,
}
};
static int __init init_mpc1211_maps(void)
{
int nr_parts;
mpc1211_flash_map.phys = 0;
mpc1211_flash_map.virt = (void __iomem *)P2SEGADDR(0);
simple_map_init(&mpc1211_flash_map);
printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n");
flash_mtd = do_map_probe("jedec_probe", &mpc1211_flash_map);
if (!flash_mtd) {
printk(KERN_NOTICE "Flash chips not detected at either possible location.\n");
return -ENXIO;
}
printk(KERN_NOTICE "MPC-1211: Flash at 0x%08lx\n", mpc1211_flash_map.virt & 0x1fffffff);
flash_mtd->module = THIS_MODULE;
parsed_parts = mpc1211_partitions;
nr_parts = ARRAY_SIZE(mpc1211_partitions);
add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
return 0;
}
static void __exit cleanup_mpc1211_maps(void)
{
if (parsed_parts)
del_mtd_partitions(flash_mtd);
else
del_mtd_device(flash_mtd);
map_destroy(flash_mtd);
}
module_init(init_mpc1211_maps);
module_exit(cleanup_mpc1211_maps);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Saito.K & Jeanne <ksaito@interface.co.jp>");
MODULE_DESCRIPTION("MTD map driver for MPC-1211 boards. Interface");

140
drivers/mtd/maps/netsc520.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,140 @@
/* netsc520.c -- MTD map driver for AMD NetSc520 Demonstration Board
*
* Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com)
* based on sc520cdp.c by Sysgo Real-Time Solutions GmbH
*
* $Id: netsc520.c,v 1.13 2004/11/28 09:40:40 dwmw2 Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* The NetSc520 is a demonstration board for the Elan Sc520 processor available
* from AMD. It has a single back of 16 megs of 32-bit Flash ROM and another
* 16 megs of SDRAM.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
/*
** The single, 16 megabyte flash bank is divided into four virtual
** partitions. The first partition is 768 KiB and is intended to
** store the kernel image loaded by the bootstrap loader. The second
** partition is 256 KiB and holds the BIOS image. The third
** partition is 14.5 MiB and is intended for the flash file system
** image. The last partition is 512 KiB and contains another copy
** of the BIOS image and the reset vector.
**
** Only the third partition should be mounted. The first partition
** should not be mounted, but it can erased and written to using the
** MTD character routines. The second and fourth partitions should
** not be touched - it is possible to corrupt the BIOS image by
** mounting these partitions, and potentially the board will not be
** recoverable afterwards.
*/
/* partition_info gives details on the logical partitions that the split the
* single flash device into. If the size if zero we use up to the end of the
* device. */
static struct mtd_partition partition_info[]={
{
.name = "NetSc520 boot kernel",
.offset = 0,
.size = 0xc0000
},
{
.name = "NetSc520 Low BIOS",
.offset = 0xc0000,
.size = 0x40000
},
{
.name = "NetSc520 file system",
.offset = 0x100000,
.size = 0xe80000
},
{
.name = "NetSc520 High BIOS",
.offset = 0xf80000,
.size = 0x80000
},
};
#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
#define WINDOW_SIZE 0x00100000
#define WINDOW_ADDR 0x00200000
static struct map_info netsc520_map = {
.name = "netsc520 Flash Bank",
.size = WINDOW_SIZE,
.bankwidth = 4,
.phys = WINDOW_ADDR,
};
#define NUM_FLASH_BANKS (sizeof(netsc520_map)/sizeof(struct map_info))
static struct mtd_info *mymtd;
static int __init init_netsc520(void)
{
printk(KERN_NOTICE "NetSc520 flash device: 0x%lx at 0x%lx\n", netsc520_map.size, netsc520_map.phys);
netsc520_map.virt = ioremap_nocache(netsc520_map.phys, netsc520_map.size);
if (!netsc520_map.virt) {
printk("Failed to ioremap_nocache\n");
return -EIO;
}
simple_map_init(&netsc520_map);
mymtd = do_map_probe("cfi_probe", &netsc520_map);
if(!mymtd)
mymtd = do_map_probe("map_ram", &netsc520_map);
if(!mymtd)
mymtd = do_map_probe("map_rom", &netsc520_map);
if (!mymtd) {
iounmap(netsc520_map.virt);
return -ENXIO;
}
mymtd->owner = THIS_MODULE;
add_mtd_partitions( mymtd, partition_info, NUM_PARTITIONS );
return 0;
}
static void __exit cleanup_netsc520(void)
{
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
if (netsc520_map.virt) {
iounmap(netsc520_map.virt);
netsc520_map.virt = NULL;
}
}
module_init(init_netsc520);
module_exit(cleanup_netsc520);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mark Langsdorf <mark.langsdorf@amd.com>");
MODULE_DESCRIPTION("MTD map driver for AMD NetSc520 Demonstration Board");

496
drivers/mtd/maps/nettel.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,496 @@
/****************************************************************************/
/*
* nettel.c -- mappings for NETtel/SecureEdge/SnapGear (x86) boards.
*
* (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com)
* (C) Copyright 2001-2002, SnapGear (www.snapgear.com)
*
* $Id: nettel.c,v 1.10 2005/01/05 17:11:29 dwmw2 Exp $
*/
/****************************************************************************/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/cfi.h>
#include <linux/reboot.h>
#include <asm/io.h>
/****************************************************************************/
#define INTEL_BUSWIDTH 1
#define AMD_WINDOW_MAXSIZE 0x00200000
#define AMD_BUSWIDTH 1
/*
* PAR masks and shifts, assuming 64K pages.
*/
#define SC520_PAR_ADDR_MASK 0x00003fff
#define SC520_PAR_ADDR_SHIFT 16
#define SC520_PAR_TO_ADDR(par) \
(((par)&SC520_PAR_ADDR_MASK) << SC520_PAR_ADDR_SHIFT)
#define SC520_PAR_SIZE_MASK 0x01ffc000
#define SC520_PAR_SIZE_SHIFT 2
#define SC520_PAR_TO_SIZE(par) \
((((par)&SC520_PAR_SIZE_MASK) << SC520_PAR_SIZE_SHIFT) + (64*1024))
#define SC520_PAR(cs, addr, size) \
((cs) | \
((((size)-(64*1024)) >> SC520_PAR_SIZE_SHIFT) & SC520_PAR_SIZE_MASK) | \
(((addr) >> SC520_PAR_ADDR_SHIFT) & SC520_PAR_ADDR_MASK))
#define SC520_PAR_BOOTCS 0x8a000000
#define SC520_PAR_ROMCS1 0xaa000000
#define SC520_PAR_ROMCS2 0xca000000 /* Cache disabled, 64K page */
static void *nettel_mmcrp = NULL;
#ifdef CONFIG_MTD_CFI_INTELEXT
static struct mtd_info *intel_mtd;
#endif
static struct mtd_info *amd_mtd;
/****************************************************************************/
/****************************************************************************/
#ifdef CONFIG_MTD_CFI_INTELEXT
static struct map_info nettel_intel_map = {
.name = "SnapGear Intel",
.size = 0,
.bankwidth = INTEL_BUSWIDTH,
};
static struct mtd_partition nettel_intel_partitions[] = {
{
.name = "SnapGear kernel",
.offset = 0,
.size = 0x000e0000
},
{
.name = "SnapGear filesystem",
.offset = 0x00100000,
},
{
.name = "SnapGear config",
.offset = 0x000e0000,
.size = 0x00020000
},
{
.name = "SnapGear Intel",
.offset = 0
},
{
.name = "SnapGear BIOS Config",
.offset = 0x007e0000,
.size = 0x00020000
},
{
.name = "SnapGear BIOS",
.offset = 0x007e0000,
.size = 0x00020000
},
};
#endif
static struct map_info nettel_amd_map = {
.name = "SnapGear AMD",
.size = AMD_WINDOW_MAXSIZE,
.bankwidth = AMD_BUSWIDTH,
};
static struct mtd_partition nettel_amd_partitions[] = {
{
.name = "SnapGear BIOS config",
.offset = 0x000e0000,
.size = 0x00010000
},
{
.name = "SnapGear BIOS",
.offset = 0x000f0000,
.size = 0x00010000
},
{
.name = "SnapGear AMD",
.offset = 0
},
{
.name = "SnapGear high BIOS",
.offset = 0x001f0000,
.size = 0x00010000
}
};
#define NUM_AMD_PARTITIONS \
(sizeof(nettel_amd_partitions)/sizeof(nettel_amd_partitions[0]))
/****************************************************************************/
#ifdef CONFIG_MTD_CFI_INTELEXT
/*
* Set the Intel flash back to read mode since some old boot
* loaders don't.
*/
static int nettel_reboot_notifier(struct notifier_block *nb, unsigned long val, void *v)
{
struct cfi_private *cfi = nettel_intel_map.fldrv_priv;
unsigned long b;
/* Make sure all FLASH chips are put back into read mode */
for (b = 0; (b < nettel_intel_partitions[3].size); b += 0x100000) {
cfi_send_gen_cmd(0xff, 0x55, b, &nettel_intel_map, cfi,
cfi->device_type, NULL);
}
return(NOTIFY_OK);
}
static struct notifier_block nettel_notifier_block = {
nettel_reboot_notifier, NULL, 0
};
/*
* Erase the configuration file system.
* Used to support the software reset button.
*/
static void nettel_erasecallback(struct erase_info *done)
{
wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
wake_up(wait_q);
}
static struct erase_info nettel_erase;
int nettel_eraseconfig(void)
{
struct mtd_info *mtd;
DECLARE_WAITQUEUE(wait, current);
wait_queue_head_t wait_q;
int ret;
init_waitqueue_head(&wait_q);
mtd = get_mtd_device(NULL, 2);
if (mtd) {
nettel_erase.mtd = mtd;
nettel_erase.callback = nettel_erasecallback;
nettel_erase.callback = NULL;
nettel_erase.addr = 0;
nettel_erase.len = mtd->size;
nettel_erase.priv = (u_long) &wait_q;
nettel_erase.priv = 0;
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&wait_q, &wait);
ret = MTD_ERASE(mtd, &nettel_erase);
if (ret) {
set_current_state(TASK_RUNNING);
remove_wait_queue(&wait_q, &wait);
put_mtd_device(mtd);
return(ret);
}
schedule(); /* Wait for erase to finish. */
remove_wait_queue(&wait_q, &wait);
put_mtd_device(mtd);
}
return(0);
}
#else
int nettel_eraseconfig(void)
{
return(0);
}
#endif
/****************************************************************************/
int __init nettel_init(void)
{
volatile unsigned long *amdpar;
unsigned long amdaddr, maxsize;
int num_amd_partitions=0;
#ifdef CONFIG_MTD_CFI_INTELEXT
volatile unsigned long *intel0par, *intel1par;
unsigned long orig_bootcspar, orig_romcs1par;
unsigned long intel0addr, intel0size;
unsigned long intel1addr, intel1size;
int intelboot, intel0cs, intel1cs;
int num_intel_partitions;
#endif
int rc = 0;
nettel_mmcrp = (void *) ioremap_nocache(0xfffef000, 4096);
if (nettel_mmcrp == NULL) {
printk("SNAPGEAR: failed to disable MMCR cache??\n");
return(-EIO);
}
/* Set CPU clock to be 33.000MHz */
*((unsigned char *) (nettel_mmcrp + 0xc64)) = 0x01;
amdpar = (volatile unsigned long *) (nettel_mmcrp + 0xc4);
#ifdef CONFIG_MTD_CFI_INTELEXT
intelboot = 0;
intel0cs = SC520_PAR_ROMCS1;
intel0par = (volatile unsigned long *) (nettel_mmcrp + 0xc0);
intel1cs = SC520_PAR_ROMCS2;
intel1par = (volatile unsigned long *) (nettel_mmcrp + 0xbc);
/*
* Save the CS settings then ensure ROMCS1 and ROMCS2 are off,
* otherwise they might clash with where we try to map BOOTCS.
*/
orig_bootcspar = *amdpar;
orig_romcs1par = *intel0par;
*intel0par = 0;
*intel1par = 0;
#endif
/*
* The first thing to do is determine if we have a separate
* boot FLASH device. Typically this is a small (1 to 2MB)
* AMD FLASH part. It seems that device size is about the
* only way to tell if this is the case...
*/
amdaddr = 0x20000000;
maxsize = AMD_WINDOW_MAXSIZE;
*amdpar = SC520_PAR(SC520_PAR_BOOTCS, amdaddr, maxsize);
__asm__ ("wbinvd");
nettel_amd_map.phys = amdaddr;
nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize);
if (!nettel_amd_map.virt) {
printk("SNAPGEAR: failed to ioremap() BOOTCS\n");
return(-EIO);
}
simple_map_init(&nettel_amd_map);
if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) {
printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n",
amd_mtd->size>>10);
amd_mtd->owner = THIS_MODULE;
/* The high BIOS partition is only present for 2MB units */
num_amd_partitions = NUM_AMD_PARTITIONS;
if (amd_mtd->size < AMD_WINDOW_MAXSIZE)
num_amd_partitions--;
/* Don't add the partition until after the primary INTEL's */
#ifdef CONFIG_MTD_CFI_INTELEXT
/*
* Map the Intel flash into memory after the AMD
* It has to start on a multiple of maxsize.
*/
maxsize = SC520_PAR_TO_SIZE(orig_romcs1par);
if (maxsize < (32 * 1024 * 1024))
maxsize = (32 * 1024 * 1024);
intel0addr = amdaddr + maxsize;
#endif
} else {
#ifdef CONFIG_MTD_CFI_INTELEXT
/* INTEL boot FLASH */
intelboot++;
if (!orig_romcs1par) {
intel0cs = SC520_PAR_BOOTCS;
intel0par = (volatile unsigned long *)
(nettel_mmcrp + 0xc4);
intel1cs = SC520_PAR_ROMCS1;
intel1par = (volatile unsigned long *)
(nettel_mmcrp + 0xc0);
intel0addr = SC520_PAR_TO_ADDR(orig_bootcspar);
maxsize = SC520_PAR_TO_SIZE(orig_bootcspar);
} else {
/* Kernel base is on ROMCS1, not BOOTCS */
intel0cs = SC520_PAR_ROMCS1;
intel0par = (volatile unsigned long *)
(nettel_mmcrp + 0xc0);
intel1cs = SC520_PAR_BOOTCS;
intel1par = (volatile unsigned long *)
(nettel_mmcrp + 0xc4);
intel0addr = SC520_PAR_TO_ADDR(orig_romcs1par);
maxsize = SC520_PAR_TO_SIZE(orig_romcs1par);
}
/* Destroy useless AMD MTD mapping */
amd_mtd = NULL;
iounmap(nettel_amd_map.virt);
nettel_amd_map.virt = NULL;
#else
/* Only AMD flash supported */
return(-ENXIO);
#endif
}
#ifdef CONFIG_MTD_CFI_INTELEXT
/*
* We have determined the INTEL FLASH configuration, so lets
* go ahead and probe for them now.
*/
/* Set PAR to the maximum size */
if (maxsize < (32 * 1024 * 1024))
maxsize = (32 * 1024 * 1024);
*intel0par = SC520_PAR(intel0cs, intel0addr, maxsize);
/* Turn other PAR off so the first probe doesn't find it */
*intel1par = 0;
/* Probe for the the size of the first Intel flash */
nettel_intel_map.size = maxsize;
nettel_intel_map.phys = intel0addr;
nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
if (!nettel_intel_map.virt) {
printk("SNAPGEAR: failed to ioremap() ROMCS1\n");
return(-EIO);
}
simple_map_init(&nettel_intel_map);
intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
if (!intel_mtd) {
iounmap(nettel_intel_map.virt);
return(-ENXIO);
}
/* Set PAR to the detected size */
intel0size = intel_mtd->size;
*intel0par = SC520_PAR(intel0cs, intel0addr, intel0size);
/*
* Map second Intel FLASH right after first. Set its size to the
* same maxsize used for the first Intel FLASH.
*/
intel1addr = intel0addr + intel0size;
*intel1par = SC520_PAR(intel1cs, intel1addr, maxsize);
__asm__ ("wbinvd");
maxsize += intel0size;
/* Delete the old map and probe again to do both chips */
map_destroy(intel_mtd);
intel_mtd = NULL;
iounmap(nettel_intel_map.virt);
nettel_intel_map.size = maxsize;
nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
if (!nettel_intel_map.virt) {
printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n");
return(-EIO);
}
intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
if (! intel_mtd) {
iounmap((void *) nettel_intel_map.virt);
return(-ENXIO);
}
intel1size = intel_mtd->size - intel0size;
if (intel1size > 0) {
*intel1par = SC520_PAR(intel1cs, intel1addr, intel1size);
__asm__ ("wbinvd");
} else {
*intel1par = 0;
}
printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n",
(intel_mtd->size >> 10));
intel_mtd->owner = THIS_MODULE;
#ifndef CONFIG_BLK_DEV_INITRD
ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1);
#endif
num_intel_partitions = sizeof(nettel_intel_partitions) /
sizeof(nettel_intel_partitions[0]);
if (intelboot) {
/*
* Adjust offset and size of last boot partition.
* Must allow for BIOS region at end of FLASH.
*/
nettel_intel_partitions[1].size = (intel0size + intel1size) -
(1024*1024 + intel_mtd->erasesize);
nettel_intel_partitions[3].size = intel0size + intel1size;
nettel_intel_partitions[4].offset =
(intel0size + intel1size) - intel_mtd->erasesize;
nettel_intel_partitions[4].size = intel_mtd->erasesize;
nettel_intel_partitions[5].offset =
nettel_intel_partitions[4].offset;
nettel_intel_partitions[5].size =
nettel_intel_partitions[4].size;
} else {
/* No BIOS regions when AMD boot */
num_intel_partitions -= 2;
}
rc = add_mtd_partitions(intel_mtd, nettel_intel_partitions,
num_intel_partitions);
#endif
if (amd_mtd) {
rc = add_mtd_partitions(amd_mtd, nettel_amd_partitions,
num_amd_partitions);
}
#ifdef CONFIG_MTD_CFI_INTELEXT
register_reboot_notifier(&nettel_notifier_block);
#endif
return(rc);
}
/****************************************************************************/
void __exit nettel_cleanup(void)
{
#ifdef CONFIG_MTD_CFI_INTELEXT
unregister_reboot_notifier(&nettel_notifier_block);
#endif
if (amd_mtd) {
del_mtd_partitions(amd_mtd);
map_destroy(amd_mtd);
}
if (nettel_amd_map.virt) {
iounmap(nettel_amd_map.virt);
nettel_amd_map.virt = NULL;
}
#ifdef CONFIG_MTD_CFI_INTELEXT
if (intel_mtd) {
del_mtd_partitions(intel_mtd);
map_destroy(intel_mtd);
}
if (nettel_intel_map.virt) {
iounmap(nettel_intel_map.virt);
nettel_intel_map.virt = 0;
}
#endif
}
/****************************************************************************/
module_init(nettel_init);
module_exit(nettel_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support");
/****************************************************************************/

175
drivers/mtd/maps/ocelot.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,175 @@
/*
* $Id: ocelot.c,v 1.16 2005/01/05 18:05:13 dwmw2 Exp $
*
* Flash on Momenco Ocelot
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#define OCELOT_PLD 0x2c000000
#define FLASH_WINDOW_ADDR 0x2fc00000
#define FLASH_WINDOW_SIZE 0x00080000
#define FLASH_BUSWIDTH 1
#define NVRAM_WINDOW_ADDR 0x2c800000
#define NVRAM_WINDOW_SIZE 0x00007FF0
#define NVRAM_BUSWIDTH 1
static unsigned int cacheflush = 0;
static struct mtd_info *flash_mtd;
static struct mtd_info *nvram_mtd;
static void ocelot_ram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
{
struct map_info *map = mtd->priv;
size_t done = 0;
/* If we use memcpy, it does word-wide writes. Even though we told the
GT64120A that it's an 8-bit wide region, word-wide writes don't work.
We end up just writing the first byte of the four to all four bytes.
So we have this loop instead */
*retlen = len;
while(len) {
__raw_writeb(*(unsigned char *) from, map->virt + to);
from++;
to++;
len--;
}
}
static struct mtd_partition *parsed_parts;
struct map_info ocelot_flash_map = {
.name = "Ocelot boot flash",
.size = FLASH_WINDOW_SIZE,
.bankwidth = FLASH_BUSWIDTH,
.phys = FLASH_WINDOW_ADDR,
};
struct map_info ocelot_nvram_map = {
.name = "Ocelot NVRAM",
.size = NVRAM_WINDOW_SIZE,
.bankwidth = NVRAM_BUSWIDTH,
.phys = NVRAM_WINDOW_ADDR,
};
static const char *probes[] = { "RedBoot", NULL };
static int __init init_ocelot_maps(void)
{
void *pld;
int nr_parts;
unsigned char brd_status;
printk(KERN_INFO "Momenco Ocelot MTD mappings: Flash 0x%x at 0x%x, NVRAM 0x%x at 0x%x\n",
FLASH_WINDOW_SIZE, FLASH_WINDOW_ADDR, NVRAM_WINDOW_SIZE, NVRAM_WINDOW_ADDR);
/* First check whether the flash jumper is present */
pld = ioremap(OCELOT_PLD, 0x10);
if (!pld) {
printk(KERN_NOTICE "Failed to ioremap Ocelot PLD\n");
return -EIO;
}
brd_status = readb(pld+4);
iounmap(pld);
/* Now ioremap the NVRAM space */
ocelot_nvram_map.virt = ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE);
if (!ocelot_nvram_map.virt) {
printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n");
return -EIO;
}
simple_map_init(&ocelot_nvram_map);
/* And do the RAM probe on it to get an MTD device */
nvram_mtd = do_map_probe("map_ram", &ocelot_nvram_map);
if (!nvram_mtd) {
printk("NVRAM probe failed\n");
goto fail_1;
}
nvram_mtd->owner = THIS_MODULE;
nvram_mtd->erasesize = 16;
/* Override the write() method */
nvram_mtd->write = ocelot_ram_write;
/* Now map the flash space */
ocelot_flash_map.virt = ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE);
if (!ocelot_flash_map.virt) {
printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n");
goto fail_2;
}
/* Now the cached version */
ocelot_flash_map.cached = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0);
simple_map_init(&ocelot_flash_map);
/* Only probe for flash if the write jumper is present */
if (brd_status & 0x40) {
flash_mtd = do_map_probe("jedec", &ocelot_flash_map);
} else {
printk(KERN_NOTICE "Ocelot flash write jumper not present. Treating as ROM\n");
}
/* If that failed or the jumper's absent, pretend it's ROM */
if (!flash_mtd) {
flash_mtd = do_map_probe("map_rom", &ocelot_flash_map);
/* If we're treating it as ROM, set the erase size */
if (flash_mtd)
flash_mtd->erasesize = 0x10000;
}
if (!flash_mtd)
goto fail3;
add_mtd_device(nvram_mtd);
flash_mtd->owner = THIS_MODULE;
nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
if (nr_parts > 0)
add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
else
add_mtd_device(flash_mtd);
return 0;
fail3:
iounmap((void *)ocelot_flash_map.virt);
if (ocelot_flash_map.cached)
iounmap((void *)ocelot_flash_map.cached);
fail_2:
map_destroy(nvram_mtd);
fail_1:
iounmap((void *)ocelot_nvram_map.virt);
return -ENXIO;
}
static void __exit cleanup_ocelot_maps(void)
{
del_mtd_device(nvram_mtd);
map_destroy(nvram_mtd);
iounmap((void *)ocelot_nvram_map.virt);
if (parsed_parts)
del_mtd_partitions(flash_mtd);
else
del_mtd_device(flash_mtd);
map_destroy(flash_mtd);
iounmap((void *)ocelot_flash_map.virt);
if (ocelot_flash_map.cached)
iounmap((void *)ocelot_flash_map.cached);
}
module_init(init_ocelot_maps);
module_exit(cleanup_ocelot_maps);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>");
MODULE_DESCRIPTION("MTD map driver for Momenco Ocelot board");

154
drivers/mtd/maps/ocotea.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,154 @@
/*
* Mapping for Ocotea user flash
*
* Matt Porter <mporter@kernel.crashing.org>
*
* Copyright 2002-2004 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/config.h>
#include <linux/version.h>
#include <asm/io.h>
#include <asm/ibm44x.h>
#include <platforms/4xx/ocotea.h>
static struct mtd_info *flash;
static struct map_info ocotea_small_map = {
.name = "Ocotea small flash",
.size = OCOTEA_SMALL_FLASH_SIZE,
.buswidth = 1,
};
static struct map_info ocotea_large_map = {
.name = "Ocotea large flash",
.size = OCOTEA_LARGE_FLASH_SIZE,
.buswidth = 1,
};
static struct mtd_partition ocotea_small_partitions[] = {
{
.name = "pibs",
.offset = 0x0,
.size = 0x100000,
}
};
static struct mtd_partition ocotea_large_partitions[] = {
{
.name = "fs",
.offset = 0,
.size = 0x300000,
},
{
.name = "firmware",
.offset = 0x300000,
.size = 0x100000,
}
};
#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
int __init init_ocotea(void)
{
u8 fpga0_reg;
u8 *fpga0_adr;
unsigned long long small_flash_base, large_flash_base;
fpga0_adr = ioremap64(OCOTEA_FPGA_ADDR, 16);
if (!fpga0_adr)
return -ENOMEM;
fpga0_reg = readb((unsigned long)fpga0_adr);
iounmap(fpga0_adr);
if (OCOTEA_BOOT_LARGE_FLASH(fpga0_reg)) {
small_flash_base = OCOTEA_SMALL_FLASH_HIGH;
large_flash_base = OCOTEA_LARGE_FLASH_LOW;
}
else {
small_flash_base = OCOTEA_SMALL_FLASH_LOW;
large_flash_base = OCOTEA_LARGE_FLASH_HIGH;
}
ocotea_small_map.phys = small_flash_base;
ocotea_small_map.virt = ioremap64(small_flash_base,
ocotea_small_map.size);
if (!ocotea_small_map.virt) {
printk("Failed to ioremap flash\n");
return -EIO;
}
simple_map_init(&ocotea_small_map);
flash = do_map_probe("map_rom", &ocotea_small_map);
if (flash) {
flash->owner = THIS_MODULE;
add_mtd_partitions(flash, ocotea_small_partitions,
NB_OF(ocotea_small_partitions));
} else {
printk("map probe failed for flash\n");
return -ENXIO;
}
ocotea_large_map.phys = large_flash_base;
ocotea_large_map.virt = ioremap64(large_flash_base,
ocotea_large_map.size);
if (!ocotea_large_map.virt) {
printk("Failed to ioremap flash\n");
return -EIO;
}
simple_map_init(&ocotea_large_map);
flash = do_map_probe("cfi_probe", &ocotea_large_map);
if (flash) {
flash->owner = THIS_MODULE;
add_mtd_partitions(flash, ocotea_large_partitions,
NB_OF(ocotea_large_partitions));
} else {
printk("map probe failed for flash\n");
return -ENXIO;
}
return 0;
}
static void __exit cleanup_ocotea(void)
{
if (flash) {
del_mtd_partitions(flash);
map_destroy(flash);
}
if (ocotea_small_map.virt) {
iounmap((void *)ocotea_small_map.virt);
ocotea_small_map.virt = 0;
}
if (ocotea_large_map.virt) {
iounmap((void *)ocotea_large_map.virt);
ocotea_large_map.virt = 0;
}
}
module_init(init_ocotea);
module_exit(cleanup_ocotea);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
MODULE_DESCRIPTION("MTD map and partitions for IBM 440GX Ocotea boards");

248
drivers/mtd/maps/octagon-5066.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,248 @@
// $Id: octagon-5066.c,v 1.26 2004/07/12 22:38:29 dwmw2 Exp $
/* ######################################################################
Octagon 5066 MTD Driver.
The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It
comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that
is replacable by flash. Both units are mapped through a multiplexer
into a 32k memory window at 0xe8000. The control register for the
multiplexing unit is located at IO 0x208 with a bit map of
0-5 Page Selection in 32k increments
6-7 Device selection:
00 SSD off
01 SSD 0 (Socket)
10 SSD 1 (Flash chip)
11 undefined
On each SSD, the first 128k is reserved for use by the bios
(actually it IS the bios..) This only matters if you are booting off the
flash, you must not put a file system starting there.
The driver tries to do a detection algorithm to guess what sort of devices
are plugged into the sockets.
##################################################################### */
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#define WINDOW_START 0xe8000
#define WINDOW_LENGTH 0x8000
#define WINDOW_SHIFT 27
#define WINDOW_MASK 0x7FFF
#define PAGE_IO 0x208
static volatile char page_n_dev = 0;
static unsigned long iomapadr;
static DEFINE_SPINLOCK(oct5066_spin);
/*
* We use map_priv_1 to identify which device we are.
*/
static void __oct5066_page(struct map_info *map, __u8 byte)
{
outb(byte,PAGE_IO);
page_n_dev = byte;
}
static inline void oct5066_page(struct map_info *map, unsigned long ofs)
{
__u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT);
if (page_n_dev != byte)
__oct5066_page(map, byte);
}
static map_word oct5066_read8(struct map_info *map, unsigned long ofs)
{
map_word ret;
spin_lock(&oct5066_spin);
oct5066_page(map, ofs);
ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK));
spin_unlock(&oct5066_spin);
return ret;
}
static void oct5066_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
while(len) {
unsigned long thislen = len;
if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
spin_lock(&oct5066_spin);
oct5066_page(map, from);
memcpy_fromio(to, iomapadr + from, thislen);
spin_unlock(&oct5066_spin);
to += thislen;
from += thislen;
len -= thislen;
}
}
static void oct5066_write8(struct map_info *map, map_word d, unsigned long adr)
{
spin_lock(&oct5066_spin);
oct5066_page(map, adr);
writeb(d.x[0], iomapadr + (adr & WINDOW_MASK));
spin_unlock(&oct5066_spin);
}
static void oct5066_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
while(len) {
unsigned long thislen = len;
if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
spin_lock(&oct5066_spin);
oct5066_page(map, to);
memcpy_toio(iomapadr + to, from, thislen);
spin_unlock(&oct5066_spin);
to += thislen;
from += thislen;
len -= thislen;
}
}
static struct map_info oct5066_map[2] = {
{
.name = "Octagon 5066 Socket",
.phys = NO_XIP,
.size = 512 * 1024,
.bankwidth = 1,
.read = oct5066_read8,
.copy_from = oct5066_copy_from,
.write = oct5066_write8,
.copy_to = oct5066_copy_to,
.map_priv_1 = 1<<6
},
{
.name = "Octagon 5066 Internal Flash",
.phys = NO_XIP,
.size = 2 * 1024 * 1024,
.bankwidth = 1,
.read = oct5066_read8,
.copy_from = oct5066_copy_from,
.write = oct5066_write8,
.copy_to = oct5066_copy_to,
.map_priv_1 = 2<<6
}
};
static struct mtd_info *oct5066_mtd[2] = {NULL, NULL};
// OctProbe - Sense if this is an octagon card
// ---------------------------------------------------------------------
/* Perform a simple validity test, we map the window select SSD0 and
change pages while monitoring the window. A change in the window,
controlled by the PAGE_IO port is a functioning 5066 board. This will
fail if the thing in the socket is set to a uniform value. */
static int __init OctProbe(void)
{
unsigned int Base = (1 << 6);
unsigned long I;
unsigned long Values[10];
for (I = 0; I != 20; I++)
{
outb(Base + (I%10),PAGE_IO);
if (I < 10)
{
// Record the value and check for uniqueness
Values[I%10] = readl(iomapadr);
if (I > 0 && Values[I%10] == Values[0])
return -EAGAIN;
}
else
{
// Make sure we get the same values on the second pass
if (Values[I%10] != readl(iomapadr))
return -EAGAIN;
}
}
return 0;
}
void cleanup_oct5066(void)
{
int i;
for (i=0; i<2; i++) {
if (oct5066_mtd[i]) {
del_mtd_device(oct5066_mtd[i]);
map_destroy(oct5066_mtd[i]);
}
}
iounmap((void *)iomapadr);
release_region(PAGE_IO, 1);
}
int __init init_oct5066(void)
{
int i;
int ret = 0;
// Do an autoprobe sequence
if (!request_region(PAGE_IO,1,"Octagon SSD")) {
printk(KERN_NOTICE "5066: Page Register in Use\n");
return -EAGAIN;
}
iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
if (!iomapadr) {
printk(KERN_NOTICE "Failed to ioremap memory region\n");
ret = -EIO;
goto out_rel;
}
if (OctProbe() != 0) {
printk(KERN_NOTICE "5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n");
iounmap((void *)iomapadr);
ret = -EAGAIN;
goto out_unmap;
}
// Print out our little header..
printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START,
WINDOW_START+WINDOW_LENGTH);
for (i=0; i<2; i++) {
oct5066_mtd[i] = do_map_probe("cfi_probe", &oct5066_map[i]);
if (!oct5066_mtd[i])
oct5066_mtd[i] = do_map_probe("jedec", &oct5066_map[i]);
if (!oct5066_mtd[i])
oct5066_mtd[i] = do_map_probe("map_ram", &oct5066_map[i]);
if (!oct5066_mtd[i])
oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]);
if (oct5066_mtd[i]) {
oct5066_mtd[i]->owner = THIS_MODULE;
add_mtd_device(oct5066_mtd[i]);
}
}
if (!oct5066_mtd[0] && !oct5066_mtd[1]) {
cleanup_oct5066();
return -ENXIO;
}
return 0;
out_unmap:
iounmap((void *)iomapadr);
out_rel:
release_region(PAGE_IO, 1);
return ret;
}
module_init(init_oct5066);
module_exit(cleanup_oct5066);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jason Gunthorpe <jgg@deltatee.com>, David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("MTD map driver for Octagon 5066 Single Board Computer");

137
drivers/mtd/maps/omap-toto-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,137 @@
/*
* NOR Flash memory access on TI Toto board
*
* jzhang@ti.com (C) 2003 Texas Instruments.
*
* (C) 2002 MontVista Software, Inc.
*
* $Id: omap-toto-flash.c,v 1.3 2004/09/16 23:27:13 gleixner Exp $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/hardware.h>
#include <asm/io.h>
#ifndef CONFIG_ARCH_OMAP
#error This is for OMAP architecture only
#endif
//these lines need be moved to a hardware header file
#define OMAP_TOTO_FLASH_BASE 0xd8000000
#define OMAP_TOTO_FLASH_SIZE 0x80000
static struct map_info omap_toto_map_flash = {
.name = "OMAP Toto flash",
.bankwidth = 2,
.virt = (void __iomem *)OMAP_TOTO_FLASH_BASE,
};
static struct mtd_partition toto_flash_partitions[] = {
{
.name = "BootLoader",
.size = 0x00040000, /* hopefully u-boot will stay 128k + 128*/
.offset = 0,
.mask_flags = MTD_WRITEABLE, /* force read-only */
}, {
.name = "ReservedSpace",
.size = 0x00030000,
.offset = MTDPART_OFS_APPEND,
//mask_flags: MTD_WRITEABLE, /* force read-only */
}, {
.name = "EnvArea", /* bottom 64KiB for env vars */
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND,
}
};
static struct mtd_partition *parsed_parts;
static struct mtd_info *flash_mtd;
static int __init init_flash (void)
{
struct mtd_partition *parts;
int nb_parts = 0;
int parsed_nr_parts = 0;
const char *part_type;
/*
* Static partition definition selection
*/
part_type = "static";
parts = toto_flash_partitions;
nb_parts = ARRAY_SIZE(toto_flash_partitions);
omap_toto_map_flash.size = OMAP_TOTO_FLASH_SIZE;
omap_toto_map_flash.phys = virt_to_phys(OMAP_TOTO_FLASH_BASE);
simple_map_init(&omap_toto_map_flash);
/*
* Now let's probe for the actual flash. Do it here since
* specific machine settings might have been set above.
*/
printk(KERN_NOTICE "OMAP toto flash: probing %d-bit flash bus\n",
omap_toto_map_flash.bankwidth*8);
flash_mtd = do_map_probe("jedec_probe", &omap_toto_map_flash);
if (!flash_mtd)
return -ENXIO;
if (parsed_nr_parts > 0) {
parts = parsed_parts;
nb_parts = parsed_nr_parts;
}
if (nb_parts == 0) {
printk(KERN_NOTICE "OMAP toto flash: no partition info available,"
"registering whole flash at once\n");
if (add_mtd_device(flash_mtd)){
return -ENXIO;
}
} else {
printk(KERN_NOTICE "Using %s partition definition\n",
part_type);
return add_mtd_partitions(flash_mtd, parts, nb_parts);
}
return 0;
}
int __init omap_toto_mtd_init(void)
{
int status;
if (status = init_flash()) {
printk(KERN_ERR "OMAP Toto Flash: unable to init map for toto flash\n");
}
return status;
}
static void __exit omap_toto_mtd_cleanup(void)
{
if (flash_mtd) {
del_mtd_partitions(flash_mtd);
map_destroy(flash_mtd);
if (parsed_parts)
kfree(parsed_parts);
}
}
module_init(omap_toto_mtd_init);
module_exit(omap_toto_mtd_cleanup);
MODULE_AUTHOR("Jian Zhang");
MODULE_DESCRIPTION("OMAP Toto board map driver");
MODULE_LICENSE("GPL");

203
drivers/mtd/maps/pb1550-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,203 @@
/*
* Flash memory access on Alchemy Pb1550 board
*
* $Id: pb1550-flash.c,v 1.6 2004/11/04 13:24:15 gleixner Exp $
*
* (C) 2004 Embedded Edge, LLC, based on pb1550-flash.c:
* (C) 2003 Pete Popov <ppopov@pacbell.net>
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/au1000.h>
#include <asm/pb1550.h>
#ifdef DEBUG_RW
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
static unsigned long window_addr;
static unsigned long window_size;
static struct map_info pb1550_map = {
.name = "Pb1550 flash",
};
static unsigned char flash_bankwidth = 4;
/*
* Support only 64MB NOR Flash parts
*/
#ifdef PB1550_BOTH_BANKS
/* both banks will be used. Combine the first bank and the first
* part of the second bank together into a single jffs/jffs2
* partition.
*/
static struct mtd_partition pb1550_partitions[] = {
/* assume boot[2:0]:swap is '0000' or '1000', which translates to:
* 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
* 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
*/
{
.name = "User FS",
.size = (0x1FC00000 - 0x18000000),
.offset = 0x0000000
},{
.name = "yamon",
.size = 0x0100000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE
},{
.name = "raw kernel",
.size = (0x300000 - 0x40000), /* last 256KB is yamon env */
.offset = MTDPART_OFS_APPEND,
}
};
#elif defined(PB1550_BOOT_ONLY)
static struct mtd_partition pb1550_partitions[] = {
/* assume boot[2:0]:swap is '0000' or '1000', which translates to:
* 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
*/
{
.name = "User FS",
.size = 0x03c00000,
.offset = 0x0000000
},{
.name = "yamon",
.size = 0x0100000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE
},{
.name = "raw kernel",
.size = (0x300000-0x40000), /* last 256KB is yamon env */
.offset = MTDPART_OFS_APPEND,
}
};
#elif defined(PB1550_USER_ONLY)
static struct mtd_partition pb1550_partitions[] = {
/* assume boot[2:0]:swap is '0000' or '1000', which translates to:
* 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
*/
{
.name = "User FS",
.size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */
.offset = 0x0000000
},{
.name = "raw kernel",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND,
}
};
#else
#error MTD_PB1550 define combo error /* should never happen */
#endif
#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
static struct mtd_info *mymtd;
/*
* Probe the flash density and setup window address and size
* based on user CONFIG options. There are times when we don't
* want the MTD driver to be probing the boot or user flash,
* so having the option to enable only one bank is important.
*/
int setup_flash_params(void)
{
u16 boot_swapboot;
boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
((bcsr->status >> 6) & 0x1);
printk("Pb1550 MTD: boot:swap %d\n", boot_swapboot);
switch (boot_swapboot) {
case 0: /* 512Mbit devices, both enabled */
case 1:
case 8:
case 9:
#if defined(PB1550_BOTH_BANKS)
window_addr = 0x18000000;
window_size = 0x8000000;
#elif defined(PB1550_BOOT_ONLY)
window_addr = 0x1C000000;
window_size = 0x4000000;
#else /* USER ONLY */
window_addr = 0x1E000000;
window_size = 0x4000000;
#endif
break;
case 0xC:
case 0xD:
case 0xE:
case 0xF:
/* 64 MB Boot NOR Flash is disabled */
/* and the start address is moved to 0x0C00000 */
window_addr = 0x0C000000;
window_size = 0x4000000;
default:
printk("Pb1550 MTD: unsupported boot:swap setting\n");
return 1;
}
return 0;
}
int __init pb1550_mtd_init(void)
{
struct mtd_partition *parts;
int nb_parts = 0;
/* Default flash bankwidth */
pb1550_map.bankwidth = flash_bankwidth;
if (setup_flash_params())
return -ENXIO;
/*
* Static partition definition selection
*/
parts = pb1550_partitions;
nb_parts = NB_OF(pb1550_partitions);
pb1550_map.size = window_size;
/*
* Now let's probe for the actual flash. Do it here since
* specific machine settings might have been set above.
*/
printk(KERN_NOTICE "Pb1550 flash: probing %d-bit flash bus\n",
pb1550_map.bankwidth*8);
pb1550_map.virt = ioremap(window_addr, window_size);
mymtd = do_map_probe("cfi_probe", &pb1550_map);
if (!mymtd) return -ENXIO;
mymtd->owner = THIS_MODULE;
add_mtd_partitions(mymtd, parts, nb_parts);
return 0;
}
static void __exit pb1550_mtd_cleanup(void)
{
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
}
module_init(pb1550_mtd_init);
module_exit(pb1550_mtd_cleanup);
MODULE_AUTHOR("Embedded Edge, LLC");
MODULE_DESCRIPTION("Pb1550 mtd map driver");
MODULE_LICENSE("GPL");

178
drivers/mtd/maps/pb1xxx-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,178 @@
/*
* Flash memory access on Alchemy Pb1xxx boards
*
* (C) 2001 Pete Popov <ppopov@mvista.com>
*
* $Id: pb1xxx-flash.c,v 1.14 2004/11/04 13:24:15 gleixner Exp $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#ifdef DEBUG_RW
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
#ifdef CONFIG_MIPS_PB1000
#define WINDOW_ADDR 0x1F800000
#define WINDOW_SIZE 0x800000
static struct mtd_partition pb1xxx_partitions[] = {
{
.name = "yamon env",
.size = 0x00020000,
.offset = 0,
.mask_flags = MTD_WRITEABLE},
{
.name = "User FS",
.size = 0x003e0000,
.offset = 0x20000,},
{
.name = "boot code",
.size = 0x100000,
.offset = 0x400000,
.mask_flags = MTD_WRITEABLE},
{
.name = "raw/kernel",
.size = 0x300000,
.offset = 0x500000}
};
#elif defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100)
#if defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER)
/* both 32MB banks will be used. Combine the first 32MB bank and the
* first 28MB of the second bank together into a single jffs/jffs2
* partition.
*/
#define WINDOW_ADDR 0x1C000000
#define WINDOW_SIZE 0x4000000
static struct mtd_partition pb1xxx_partitions[] = {
{
.name = "User FS",
.size = 0x3c00000,
.offset = 0x0000000
},{
.name = "yamon",
.size = 0x0100000,
.offset = 0x3c00000,
.mask_flags = MTD_WRITEABLE
},{
.name = "raw kernel",
.size = 0x02c0000,
.offset = 0x3d00000
}
};
#elif defined(CONFIG_MTD_PB1500_BOOT) && !defined(CONFIG_MTD_PB1500_USER)
#define WINDOW_ADDR 0x1E000000
#define WINDOW_SIZE 0x2000000
static struct mtd_partition pb1xxx_partitions[] = {
{
.name = "User FS",
.size = 0x1c00000,
.offset = 0x0000000
},{
.name = "yamon",
.size = 0x0100000,
.offset = 0x1c00000,
.mask_flags = MTD_WRITEABLE
},{
.name = "raw kernel",
.size = 0x02c0000,
.offset = 0x1d00000
}
};
#elif !defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER)
#define WINDOW_ADDR 0x1C000000
#define WINDOW_SIZE 0x2000000
static struct mtd_partition pb1xxx_partitions[] = {
{
.name = "User FS",
.size = 0x1e00000,
.offset = 0x0000000
},{
.name = "raw kernel",
.size = 0x0200000,
.offset = 0x1e00000,
}
};
#else
#error MTD_PB1500 define combo error /* should never happen */
#endif
#else
#error Unsupported board
#endif
#define NAME "Pb1x00 Linux Flash"
#define PADDR WINDOW_ADDR
#define BUSWIDTH 4
#define SIZE WINDOW_SIZE
#define PARTITIONS 4
static struct map_info pb1xxx_mtd_map = {
.name = NAME,
.size = SIZE,
.bankwidth = BUSWIDTH,
.phys = PADDR,
};
static struct mtd_info *pb1xxx_mtd;
int __init pb1xxx_mtd_init(void)
{
struct mtd_partition *parts;
int nb_parts = 0;
char *part_type;
/*
* Static partition definition selection
*/
part_type = "static";
parts = pb1xxx_partitions;
nb_parts = ARRAY_SIZE(pb1xxx_partitions);
/*
* Now let's probe for the actual flash. Do it here since
* specific machine settings might have been set above.
*/
printk(KERN_NOTICE "Pb1xxx flash: probing %d-bit flash bus\n",
BUSWIDTH*8);
pb1xxx_mtd_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
simple_map_init(&pb1xxx_mtd_map);
pb1xxx_mtd = do_map_probe("cfi_probe", &pb1xxx_mtd_map);
if (!pb1xxx_mtd) return -ENXIO;
pb1xxx_mtd->owner = THIS_MODULE;
add_mtd_partitions(pb1xxx_mtd, parts, nb_parts);
return 0;
}
static void __exit pb1xxx_mtd_cleanup(void)
{
if (pb1xxx_mtd) {
del_mtd_partitions(pb1xxx_mtd);
map_destroy(pb1xxx_mtd);
iounmap((void *) pb1xxx_mtd_map.virt);
}
}
module_init(pb1xxx_mtd_init);
module_exit(pb1xxx_mtd_cleanup);
MODULE_AUTHOR("Pete Popov");
MODULE_DESCRIPTION("Pb1xxx CFI map driver");
MODULE_LICENSE("GPL");

388
drivers/mtd/maps/pci.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,388 @@
/*
* linux/drivers/mtd/maps/pci.c
*
* Copyright (C) 2001 Russell King, All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* $Id: pci.c,v 1.9 2004/11/28 09:40:40 dwmw2 Exp $
*
* Generic PCI memory map driver. We support the following boards:
* - Intel IQ80310 ATU.
* - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
struct map_pci_info;
struct mtd_pci_info {
int (*init)(struct pci_dev *dev, struct map_pci_info *map);
void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
const char *map_name;
};
struct map_pci_info {
struct map_info map;
void __iomem *base;
void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
struct pci_dev *dev;
};
static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
map_word val;
val.x[0]= readb(map->base + map->translate(map, ofs));
// printk("read8 : %08lx => %02x\n", ofs, val.x[0]);
return val;
}
#if 0
static map_word mtd_pci_read16(struct map_info *_map, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
map_word val;
val.x[0] = readw(map->base + map->translate(map, ofs));
// printk("read16: %08lx => %04x\n", ofs, val.x[0]);
return val;
}
#endif
static map_word mtd_pci_read32(struct map_info *_map, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
map_word val;
val.x[0] = readl(map->base + map->translate(map, ofs));
// printk("read32: %08lx => %08x\n", ofs, val.x[0]);
return val;
}
static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
memcpy_fromio(to, map->base + map->translate(map, from), len);
}
static void mtd_pci_write8(struct map_info *_map, map_word val, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
// printk("write8 : %08lx <= %02x\n", ofs, val.x[0]);
writeb(val.x[0], map->base + map->translate(map, ofs));
}
#if 0
static void mtd_pci_write16(struct map_info *_map, map_word val, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
// printk("write16: %08lx <= %04x\n", ofs, val.x[0]);
writew(val.x[0], map->base + map->translate(map, ofs));
}
#endif
static void mtd_pci_write32(struct map_info *_map, map_word val, unsigned long ofs)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
// printk("write32: %08lx <= %08x\n", ofs, val.x[0]);
writel(val.x[0], map->base + map->translate(map, ofs));
}
static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
{
struct map_pci_info *map = (struct map_pci_info *)_map;
memcpy_toio(map->base + map->translate(map, to), from, len);
}
static struct map_info mtd_pci_map = {
.phys = NO_XIP,
.copy_from = mtd_pci_copyfrom,
.copy_to = mtd_pci_copyto,
};
/*
* Intel IOP80310 Flash driver
*/
static int
intel_iq80310_init(struct pci_dev *dev, struct map_pci_info *map)
{
u32 win_base;
map->map.bankwidth = 1;
map->map.read = mtd_pci_read8,
map->map.write = mtd_pci_write8,
map->map.size = 0x00800000;
map->base = ioremap_nocache(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
if (!map->base)
return -ENOMEM;
/*
* We want to base the memory window at Xscale
* bus address 0, not 0x1000.
*/
pci_read_config_dword(dev, 0x44, &win_base);
pci_write_config_dword(dev, 0x44, 0);
map->map.map_priv_2 = win_base;
return 0;
}
static void
intel_iq80310_exit(struct pci_dev *dev, struct map_pci_info *map)
{
if (map->base)
iounmap(map->base);
pci_write_config_dword(dev, 0x44, map->map.map_priv_2);
}
static unsigned long
intel_iq80310_translate(struct map_pci_info *map, unsigned long ofs)
{
unsigned long page_addr = ofs & 0x00400000;
/*
* This mundges the flash location so we avoid
* the first 80 bytes (they appear to read nonsense).
*/
if (page_addr) {
writel(0x00000008, map->base + 0x1558);
writel(0x00000000, map->base + 0x1550);
} else {
writel(0x00000007, map->base + 0x1558);
writel(0x00800000, map->base + 0x1550);
ofs += 0x00800000;
}
return ofs;
}
static struct mtd_pci_info intel_iq80310_info = {
.init = intel_iq80310_init,
.exit = intel_iq80310_exit,
.translate = intel_iq80310_translate,
.map_name = "cfi_probe",
};
/*
* Intel DC21285 driver
*/
static int
intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
{
unsigned long base, len;
base = pci_resource_start(dev, PCI_ROM_RESOURCE);
len = pci_resource_len(dev, PCI_ROM_RESOURCE);
if (!len || !base) {
/*
* No ROM resource
*/
base = pci_resource_start(dev, 2);
len = pci_resource_len(dev, 2);
/*
* We need to re-allocate PCI BAR2 address range to the
* PCI ROM BAR, and disable PCI BAR2.
*/
} else {
/*
* Hmm, if an address was allocated to the ROM resource, but
* not enabled, should we be allocating a new resource for it
* or simply enabling it?
*/
if (!(pci_resource_flags(dev, PCI_ROM_RESOURCE) &
IORESOURCE_ROM_ENABLE)) {
u32 val;
pci_resource_flags(dev, PCI_ROM_RESOURCE) |= IORESOURCE_ROM_ENABLE;
pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
val |= PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
printk("%s: enabling expansion ROM\n", pci_name(dev));
}
}
if (!len || !base)
return -ENXIO;
map->map.bankwidth = 4;
map->map.read = mtd_pci_read32,
map->map.write = mtd_pci_write32,
map->map.size = len;
map->base = ioremap_nocache(base, len);
if (!map->base)
return -ENOMEM;
return 0;
}
static void
intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map)
{
u32 val;
if (map->base)
iounmap(map->base);
/*
* We need to undo the PCI BAR2/PCI ROM BAR address alteration.
*/
pci_resource_flags(dev, PCI_ROM_RESOURCE) &= ~IORESOURCE_ROM_ENABLE;
pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
val &= ~PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
}
static unsigned long
intel_dc21285_translate(struct map_pci_info *map, unsigned long ofs)
{
return ofs & 0x00ffffc0 ? ofs : (ofs ^ (1 << 5));
}
static struct mtd_pci_info intel_dc21285_info = {
.init = intel_dc21285_init,
.exit = intel_dc21285_exit,
.translate = intel_dc21285_translate,
.map_name = "jedec_probe",
};
/*
* PCI device ID table
*/
static struct pci_device_id mtd_pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x530d,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.class = PCI_CLASS_MEMORY_OTHER << 8,
.class_mask = 0xffff00,
.driver_data = (unsigned long)&intel_iq80310_info,
},
{
.vendor = PCI_VENDOR_ID_DEC,
.device = PCI_DEVICE_ID_DEC_21285,
.subvendor = 0, /* DC21285 defaults to 0 on reset */
.subdevice = 0, /* DC21285 defaults to 0 on reset */
.driver_data = (unsigned long)&intel_dc21285_info,
},
{ 0, }
};
/*
* Generic code follows.
*/
static int __devinit
mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
struct map_pci_info *map = NULL;
struct mtd_info *mtd = NULL;
int err;
err = pci_enable_device(dev);
if (err)
goto out;
err = pci_request_regions(dev, "pci mtd");
if (err)
goto out;
map = kmalloc(sizeof(*map), GFP_KERNEL);
err = -ENOMEM;
if (!map)
goto release;
map->map = mtd_pci_map;
map->map.name = pci_name(dev);
map->dev = dev;
map->exit = info->exit;
map->translate = info->translate;
err = info->init(dev, map);
if (err)
goto release;
/* tsk - do_map_probe should take const char * */
mtd = do_map_probe((char *)info->map_name, &map->map);
err = -ENODEV;
if (!mtd)
goto release;
mtd->owner = THIS_MODULE;
add_mtd_device(mtd);
pci_set_drvdata(dev, mtd);
return 0;
release:
if (mtd)
map_destroy(mtd);
if (map) {
map->exit(dev, map);
kfree(map);
}
pci_release_regions(dev);
out:
return err;
}
static void __devexit
mtd_pci_remove(struct pci_dev *dev)
{
struct mtd_info *mtd = pci_get_drvdata(dev);
struct map_pci_info *map = mtd->priv;
del_mtd_device(mtd);
map_destroy(mtd);
map->exit(dev, map);
kfree(map);
pci_set_drvdata(dev, NULL);
pci_release_regions(dev);
}
static struct pci_driver mtd_pci_driver = {
.name = "MTD PCI",
.probe = mtd_pci_probe,
.remove = __devexit_p(mtd_pci_remove),
.id_table = mtd_pci_ids,
};
static int __init mtd_pci_maps_init(void)
{
return pci_module_init(&mtd_pci_driver);
}
static void __exit mtd_pci_maps_exit(void)
{
pci_unregister_driver(&mtd_pci_driver);
}
module_init(mtd_pci_maps_init);
module_exit(mtd_pci_maps_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_DESCRIPTION("Generic PCI map driver");
MODULE_DEVICE_TABLE(pci, mtd_pci_ids);

860
drivers/mtd/maps/pcmciamtd.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,860 @@
/*
* $Id: pcmciamtd.c,v 1.51 2004/07/12 22:38:29 dwmw2 Exp $
*
* pcmciamtd.c - MTD driver for PCMCIA flash memory cards
*
* Author: Simon Evans <spse@secret.org.uk>
*
* Copyright (C) 2002 Simon Evans
*
* Licence: GPL
*
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/system.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#ifdef CONFIG_MTD_DEBUG
static int debug = CONFIG_MTD_DEBUG_VERBOSE;
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
#undef DEBUG
#define DEBUG(n, format, arg...) \
if (n <= debug) { \
printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
}
#else
#undef DEBUG
#define DEBUG(n, arg...)
static const int debug = 0;
#endif
#define err(format, arg...) printk(KERN_ERR "pcmciamtd: " format "\n" , ## arg)
#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "pcmciamtd: " format "\n" , ## arg)
#define DRIVER_DESC "PCMCIA Flash memory card driver"
#define DRIVER_VERSION "$Revision: 1.51 $"
/* Size of the PCMCIA address space: 26 bits = 64 MB */
#define MAX_PCMCIA_ADDR 0x4000000
struct pcmciamtd_dev {
dev_link_t link; /* PCMCIA link */
dev_node_t node; /* device node */
caddr_t win_base; /* ioremapped address of PCMCIA window */
unsigned int win_size; /* size of window */
unsigned int offset; /* offset into card the window currently points at */
struct map_info pcmcia_map;
struct mtd_info *mtd_info;
int vpp;
char mtd_name[sizeof(struct cistpl_vers_1_t)];
};
static dev_info_t dev_info = "pcmciamtd";
static dev_link_t *dev_list;
/* Module parameters */
/* 2 = do 16-bit transfers, 1 = do 8-bit transfers */
static int bankwidth = 2;
/* Speed of memory accesses, in ns */
static int mem_speed;
/* Force the size of an SRAM card */
static int force_size;
/* Force Vpp */
static int vpp;
/* Set Vpp */
static int setvpp;
/* Force card to be treated as FLASH, ROM or RAM */
static int mem_type;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_PARM(bankwidth, "i");
MODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)");
MODULE_PARM(mem_speed, "i");
MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns");
MODULE_PARM(force_size, "i");
MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)");
MODULE_PARM(setvpp, "i");
MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)");
MODULE_PARM(vpp, "i");
MODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)");
MODULE_PARM(mem_type, "i");
MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)");
/* read/write{8,16} copy_{from,to} routines with window remapping to access whole card */
static caddr_t remap_window(struct map_info *map, unsigned long to)
{
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
window_handle_t win = (window_handle_t)map->map_priv_2;
memreq_t mrq;
int ret;
if(!(dev->link.state & DEV_PRESENT)) {
DEBUG(1, "device removed state = 0x%4.4X", dev->link.state);
return 0;
}
mrq.CardOffset = to & ~(dev->win_size-1);
if(mrq.CardOffset != dev->offset) {
DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
dev->offset, mrq.CardOffset);
mrq.Page = 0;
if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) {
cs_error(dev->link.handle, MapMemPage, ret);
return NULL;
}
dev->offset = mrq.CardOffset;
}
return dev->win_base + (to & (dev->win_size-1));
}
static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
{
caddr_t addr;
map_word d = {{0}};
addr = remap_window(map, ofs);
if(!addr)
return d;
d.x[0] = readb(addr);
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, addr, d.x[0]);
return d;
}
static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
{
caddr_t addr;
map_word d = {{0}};
addr = remap_window(map, ofs);
if(!addr)
return d;
d.x[0] = readw(addr);
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, addr, d.x[0]);
return d;
}
static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
unsigned long win_size = dev->win_size;
DEBUG(3, "to = %p from = %lu len = %u", to, from, len);
while(len) {
int toread = win_size - (from & (win_size-1));
caddr_t addr;
if(toread > len)
toread = len;
addr = remap_window(map, from);
if(!addr)
return;
DEBUG(4, "memcpy from %p to %p len = %d", addr, to, toread);
memcpy_fromio(to, addr, toread);
len -= toread;
to += toread;
from += toread;
}
}
static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long adr)
{
caddr_t addr = remap_window(map, adr);
if(!addr)
return;
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, addr, d.x[0]);
writeb(d.x[0], addr);
}
static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long adr)
{
caddr_t addr = remap_window(map, adr);
if(!addr)
return;
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, addr, d.x[0]);
writew(d.x[0], addr);
}
static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
unsigned long win_size = dev->win_size;
DEBUG(3, "to = %lu from = %p len = %u", to, from, len);
while(len) {
int towrite = win_size - (to & (win_size-1));
caddr_t addr;
if(towrite > len)
towrite = len;
addr = remap_window(map, to);
if(!addr)
return;
DEBUG(4, "memcpy from %p to %p len = %d", from, addr, towrite);
memcpy_toio(addr, from, towrite);
len -= towrite;
to += towrite;
from += towrite;
}
}
/* read/write{8,16} copy_{from,to} routines with direct access */
#define DEV_REMOVED(x) (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))
static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
{
caddr_t win_base = (caddr_t)map->map_priv_2;
map_word d = {{0}};
if(DEV_REMOVED(map))
return d;
d.x[0] = readb(win_base + ofs);
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d.x[0]);
return d;
}
static map_word pcmcia_read16(struct map_info *map, unsigned long ofs)
{
caddr_t win_base = (caddr_t)map->map_priv_2;
map_word d = {{0}};
if(DEV_REMOVED(map))
return d;
d.x[0] = readw(win_base + ofs);
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d.x[0]);
return d;
}
static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
caddr_t win_base = (caddr_t)map->map_priv_2;
if(DEV_REMOVED(map))
return;
DEBUG(3, "to = %p from = %lu len = %u", to, from, len);
memcpy_fromio(to, win_base + from, len);
}
static void pcmcia_write8(struct map_info *map, u8 d, unsigned long adr)
{
caddr_t win_base = (caddr_t)map->map_priv_2;
if(DEV_REMOVED(map))
return;
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, win_base + adr, d);
writeb(d, win_base + adr);
}
static void pcmcia_write16(struct map_info *map, u16 d, unsigned long adr)
{
caddr_t win_base = (caddr_t)map->map_priv_2;
if(DEV_REMOVED(map))
return;
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, win_base + adr, d);
writew(d, win_base + adr);
}
static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
caddr_t win_base = (caddr_t)map->map_priv_2;
if(DEV_REMOVED(map))
return;
DEBUG(3, "to = %lu from = %p len = %u", to, from, len);
memcpy_toio(win_base + to, from, len);
}
static void pcmciamtd_set_vpp(struct map_info *map, int on)
{
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
dev_link_t *link = &dev->link;
modconf_t mod;
int ret;
mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;
mod.Vcc = 0;
mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
ret = pcmcia_modify_configuration(link->handle, &mod);
if(ret != CS_SUCCESS) {
cs_error(link->handle, ModifyConfiguration, ret);
}
}
/* After a card is removed, pcmciamtd_release() will unregister the
* device, and release the PCMCIA configuration. If the device is
* still open, this will be postponed until it is closed.
*/
static void pcmciamtd_release(dev_link_t *link)
{
struct pcmciamtd_dev *dev = link->priv;
DEBUG(3, "link = 0x%p", link);
if (link->win) {
if(dev->win_base) {
iounmap(dev->win_base);
dev->win_base = NULL;
}
pcmcia_release_window(link->win);
}
pcmcia_release_configuration(link->handle);
link->state &= ~DEV_CONFIG;
}
static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name)
{
int rc;
tuple_t tuple;
cisparse_t parse;
u_char buf[64];
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = RETURN_FIRST_TUPLE;
rc = pcmcia_get_first_tuple(link->handle, &tuple);
while(rc == CS_SUCCESS) {
rc = pcmcia_get_tuple_data(link->handle, &tuple);
if(rc != CS_SUCCESS) {
cs_error(link->handle, GetTupleData, rc);
break;
}
rc = pcmcia_parse_tuple(link->handle, &tuple, &parse);
if(rc != CS_SUCCESS) {
cs_error(link->handle, ParseTuple, rc);
break;
}
switch(tuple.TupleCode) {
case CISTPL_FORMAT: {
cistpl_format_t *t = &parse.format;
(void)t; /* Shut up, gcc */
DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u",
t->type, t->edc, t->offset, t->length);
break;
}
case CISTPL_DEVICE: {
cistpl_device_t *t = &parse.device;
int i;
DEBUG(2, "Common memory:");
dev->pcmcia_map.size = t->dev[0].size;
for(i = 0; i < t->ndev; i++) {
DEBUG(2, "Region %d, type = %u", i, t->dev[i].type);
DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp);
DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed);
DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size);
}
break;
}
case CISTPL_VERS_1: {
cistpl_vers_1_t *t = &parse.version_1;
int i;
if(t->ns) {
dev->mtd_name[0] = '\0';
for(i = 0; i < t->ns; i++) {
if(i)
strcat(dev->mtd_name, " ");
strcat(dev->mtd_name, t->str+t->ofs[i]);
}
}
DEBUG(2, "Found name: %s", dev->mtd_name);
break;
}
case CISTPL_JEDEC_C: {
cistpl_jedec_t *t = &parse.jedec;
int i;
for(i = 0; i < t->nid; i++) {
DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info);
}
break;
}
case CISTPL_DEVICE_GEO: {
cistpl_device_geo_t *t = &parse.device_geo;
int i;
dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
for(i = 0; i < t->ngeo; i++) {
DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth);
DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block);
DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block);
DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block);
DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition);
DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave);
}
break;
}
default:
DEBUG(2, "Unknown tuple code %d", tuple.TupleCode);
}
rc = pcmcia_get_next_tuple(link->handle, &tuple);
}
if(!dev->pcmcia_map.size)
dev->pcmcia_map.size = MAX_PCMCIA_ADDR;
if(!dev->pcmcia_map.bankwidth)
dev->pcmcia_map.bankwidth = 2;
if(force_size) {
dev->pcmcia_map.size = force_size << 20;
DEBUG(2, "size forced to %dM", force_size);
}
if(bankwidth) {
dev->pcmcia_map.bankwidth = bankwidth;
DEBUG(2, "bankwidth forced to %d", bankwidth);
}
dev->pcmcia_map.name = dev->mtd_name;
if(!dev->mtd_name[0]) {
strcpy(dev->mtd_name, "PCMCIA Memory card");
*new_name = 1;
}
DEBUG(1, "Device: Size: %lu Width:%d Name: %s",
dev->pcmcia_map.size, dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
}
/* pcmciamtd_config() is scheduled to run after a CARD_INSERTION event
* is received, to configure the PCMCIA socket, and to make the
* MTD device available to the system.
*/
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static void pcmciamtd_config(dev_link_t *link)
{
struct pcmciamtd_dev *dev = link->priv;
struct mtd_info *mtd = NULL;
cs_status_t status;
win_req_t req;
int last_ret = 0, last_fn = 0;
int ret;
int i;
config_info_t t;
static char *probes[] = { "jedec_probe", "cfi_probe" };
cisinfo_t cisinfo;
int new_name = 0;
DEBUG(3, "link=0x%p", link);
/* Configure card */
link->state |= DEV_CONFIG;
DEBUG(2, "Validating CIS");
ret = pcmcia_validate_cis(link->handle, &cisinfo);
if(ret != CS_SUCCESS) {
cs_error(link->handle, GetTupleData, ret);
} else {
DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains);
}
card_settings(dev, link, &new_name);
dev->pcmcia_map.phys = NO_XIP;
dev->pcmcia_map.copy_from = pcmcia_copy_from_remap;
dev->pcmcia_map.copy_to = pcmcia_copy_to_remap;
if (dev->pcmcia_map.bankwidth == 1) {
dev->pcmcia_map.read = pcmcia_read8_remap;
dev->pcmcia_map.write = pcmcia_write8_remap;
} else {
dev->pcmcia_map.read = pcmcia_read16_remap;
dev->pcmcia_map.write = pcmcia_write16_remap;
}
if(setvpp == 1)
dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;
/* Request a memory window for PCMCIA. Some architeures can map windows upto the maximum
that PCMCIA can support (64MiB) - this is ideal and we aim for a window the size of the
whole card - otherwise we try smaller windows until we succeed */
req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE;
req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
req.Base = 0;
req.AccessSpeed = mem_speed;
link->win = (window_handle_t)link->handle;
req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
dev->win_size = 0;
do {
int ret;
DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
req.Size >> 10, req.AccessSpeed);
ret = pcmcia_request_window(&link->handle, &req, &link->win);
DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
if(ret) {
req.Size >>= 1;
} else {
DEBUG(2, "Got window of size %dKiB", req.Size >> 10);
dev->win_size = req.Size;
break;
}
} while(req.Size >= 0x1000);
DEBUG(2, "dev->win_size = %d", dev->win_size);
if(!dev->win_size) {
err("Cant allocate memory window");
pcmciamtd_release(link);
return;
}
DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
/* Get write protect status */
CS_CHECK(GetStatus, pcmcia_get_status(link->handle, &status));
DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx",
status.CardState, (unsigned long)link->win);
dev->win_base = ioremap(req.Base, req.Size);
if(!dev->win_base) {
err("ioremap(%lu, %u) failed", req.Base, req.Size);
pcmciamtd_release(link);
return;
}
DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
dev, req.Base, dev->win_base, req.Size);
dev->offset = 0;
dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
DEBUG(2, "Getting configuration");
CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link->handle, &t));
DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2);
dev->vpp = (vpp) ? vpp : t.Vpp1;
link->conf.Attributes = 0;
link->conf.Vcc = t.Vcc;
if(setvpp == 2) {
link->conf.Vpp1 = dev->vpp;
link->conf.Vpp2 = dev->vpp;
} else {
link->conf.Vpp1 = 0;
link->conf.Vpp2 = 0;
}
link->conf.IntType = INT_MEMORY;
link->conf.ConfigBase = t.ConfigBase;
link->conf.Status = t.Status;
link->conf.Pin = t.Pin;
link->conf.Copy = t.Copy;
link->conf.ExtStatus = t.ExtStatus;
link->conf.ConfigIndex = 0;
link->conf.Present = t.Present;
DEBUG(2, "Setting Configuration");
ret = pcmcia_request_configuration(link->handle, &link->conf);
if(ret != CS_SUCCESS) {
cs_error(link->handle, RequestConfiguration, ret);
}
if(mem_type == 1) {
mtd = do_map_probe("map_ram", &dev->pcmcia_map);
} else if(mem_type == 2) {
mtd = do_map_probe("map_rom", &dev->pcmcia_map);
} else {
for(i = 0; i < sizeof(probes) / sizeof(char *); i++) {
DEBUG(1, "Trying %s", probes[i]);
mtd = do_map_probe(probes[i], &dev->pcmcia_map);
if(mtd)
break;
DEBUG(1, "FAILED: %s", probes[i]);
}
}
if(!mtd) {
DEBUG(1, "Cant find an MTD");
pcmciamtd_release(link);
return;
}
dev->mtd_info = mtd;
mtd->owner = THIS_MODULE;
if(new_name) {
int size = 0;
char unit = ' ';
/* Since we are using a default name, make it better by adding in the
size */
if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */
size = mtd->size >> 10;
unit = 'K';
} else {
size = mtd->size >> 20;
unit = 'M';
}
snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card");
}
/* If the memory found is fits completely into the mapped PCMCIA window,
use the faster non-remapping read/write functions */
if(mtd->size <= dev->win_size) {
DEBUG(1, "Using non remapping memory functions");
dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state);
dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
if (dev->pcmcia_map.bankwidth == 1) {
dev->pcmcia_map.read = pcmcia_read8;
dev->pcmcia_map.write = pcmcia_write8;
} else {
dev->pcmcia_map.read = pcmcia_read16;
dev->pcmcia_map.write = pcmcia_write16;
}
dev->pcmcia_map.copy_from = pcmcia_copy_from;
dev->pcmcia_map.copy_to = pcmcia_copy_to;
}
if(add_mtd_device(mtd)) {
map_destroy(mtd);
dev->mtd_info = NULL;
err("Couldnt register MTD device");
pcmciamtd_release(link);
return;
}
snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index);
info("mtd%d: %s", mtd->index, mtd->name);
link->state &= ~DEV_CONFIG_PENDING;
link->dev = &dev->node;
return;
cs_failed:
cs_error(link->handle, last_fn, last_ret);
err("CS Error, exiting");
pcmciamtd_release(link);
return;
}
/* The card status event handler. Mostly, this schedules other
* stuff to run after an event is received. A CARD_REMOVAL event
* also sets some flags to discourage the driver from trying
* to talk to the card any more.
*/
static int pcmciamtd_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
DEBUG(1, "event=0x%06x", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
DEBUG(2, "EVENT_CARD_REMOVAL");
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
struct pcmciamtd_dev *dev = link->priv;
if(dev->mtd_info) {
del_mtd_device(dev->mtd_info);
info("mtd%d: Removed", dev->mtd_info->index);
}
pcmciamtd_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
DEBUG(2, "EVENT_CARD_INSERTION");
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
pcmciamtd_config(link);
break;
case CS_EVENT_PM_SUSPEND:
DEBUG(2, "EVENT_PM_SUSPEND");
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
DEBUG(2, "EVENT_RESET_PHYSICAL");
/* get_lock(link); */
break;
case CS_EVENT_PM_RESUME:
DEBUG(2, "EVENT_PM_RESUME");
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
DEBUG(2, "EVENT_CARD_RESET");
/* free_lock(link); */
break;
default:
DEBUG(2, "Unknown event %d", event);
}
return 0;
}
/* This deletes a driver "instance". The device is de-registered
* with Card Services. If it has been released, all local data
* structures are freed. Otherwise, the structures will be freed
* when the device is released.
*/
static void pcmciamtd_detach(dev_link_t *link)
{
DEBUG(3, "link=0x%p", link);
if(link->state & DEV_CONFIG) {
pcmciamtd_release(link);
}
if (link->handle) {
int ret;
DEBUG(2, "Deregistering with card services");
ret = pcmcia_deregister_client(link->handle);
if (ret != CS_SUCCESS)
cs_error(link->handle, DeregisterClient, ret);
}
link->state |= DEV_STALE_LINK;
}
/* pcmciamtd_attach() creates an "instance" of the driver, allocating
* local data structures for one device. The device is registered
* with Card Services.
*/
static dev_link_t *pcmciamtd_attach(void)
{
struct pcmciamtd_dev *dev;
dev_link_t *link;
client_reg_t client_reg;
int ret;
/* Create new memory card device */
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) return NULL;
DEBUG(1, "dev=0x%p", dev);
memset(dev, 0, sizeof(*dev));
link = &dev->link;
link->priv = dev;
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY;
link->next = dev_list;
dev_list = link;
/* Register with Card Services */
client_reg.dev_info = &dev_info;
client_reg.EventMask =
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
client_reg.event_handler = &pcmciamtd_event;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
DEBUG(2, "Calling RegisterClient");
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
pcmciamtd_detach(link);
return NULL;
}
DEBUG(2, "link = %p", link);
return link;
}
static struct pcmcia_driver pcmciamtd_driver = {
.drv = {
.name = "pcmciamtd"
},
.attach = pcmciamtd_attach,
.detach = pcmciamtd_detach,
.owner = THIS_MODULE
};
static int __init init_pcmciamtd(void)
{
info(DRIVER_DESC " " DRIVER_VERSION);
if(bankwidth && bankwidth != 1 && bankwidth != 2) {
info("bad bankwidth (%d), using default", bankwidth);
bankwidth = 2;
}
if(force_size && (force_size < 1 || force_size > 64)) {
info("bad force_size (%d), using default", force_size);
force_size = 0;
}
if(mem_type && mem_type != 1 && mem_type != 2) {
info("bad mem_type (%d), using default", mem_type);
mem_type = 0;
}
return pcmcia_register_driver(&pcmciamtd_driver);
}
static void __exit exit_pcmciamtd(void)
{
DEBUG(1, DRIVER_DESC " unloading");
pcmcia_unregister_driver(&pcmciamtd_driver);
BUG_ON(dev_list != NULL);
}
module_init(init_pcmciamtd);
module_exit(exit_pcmciamtd);

125
drivers/mtd/maps/physmap.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,125 @@
/*
* $Id: physmap.c,v 1.37 2004/11/28 09:40:40 dwmw2 Exp $
*
* Normal mappings of chips in physical memory
*
* Copyright (C) 2003 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*
* 031022 - [jsun] add run-time configure and partition setup
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/config.h>
#include <linux/mtd/partitions.h>
static struct mtd_info *mymtd;
struct map_info physmap_map = {
.name = "phys_mapped_flash",
.phys = CONFIG_MTD_PHYSMAP_START,
.size = CONFIG_MTD_PHYSMAP_LEN,
.bankwidth = CONFIG_MTD_PHYSMAP_BANKWIDTH,
};
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition *mtd_parts;
static int mtd_parts_nb;
static int num_physmap_partitions;
static struct mtd_partition *physmap_partitions;
static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
{
physmap_partitions=parts;
num_physmap_partitions=num_parts;
}
#endif /* CONFIG_MTD_PARTITIONS */
static int __init init_physmap(void)
{
static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
const char **type;
printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys);
physmap_map.virt = ioremap(physmap_map.phys, physmap_map.size);
if (!physmap_map.virt) {
printk("Failed to ioremap\n");
return -EIO;
}
simple_map_init(&physmap_map);
mymtd = NULL;
type = rom_probe_types;
for(; !mymtd && *type; type++) {
mymtd = do_map_probe(*type, &physmap_map);
}
if (mymtd) {
mymtd->owner = THIS_MODULE;
#ifdef CONFIG_MTD_PARTITIONS
mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes,
&mtd_parts, 0);
if (mtd_parts_nb > 0)
{
add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);
return 0;
}
if (num_physmap_partitions != 0)
{
printk(KERN_NOTICE
"Using physmap partition definition\n");
add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions);
return 0;
}
#endif
add_mtd_device(mymtd);
return 0;
}
iounmap(physmap_map.virt);
return -ENXIO;
}
static void __exit cleanup_physmap(void)
{
#ifdef CONFIG_MTD_PARTITIONS
if (mtd_parts_nb) {
del_mtd_partitions(mymtd);
kfree(mtd_parts);
} else if (num_physmap_partitions) {
del_mtd_partitions(mymtd);
} else {
del_mtd_device(mymtd);
}
#else
del_mtd_device(mymtd);
#endif
map_destroy(mymtd);
iounmap(physmap_map.virt);
physmap_map.virt = NULL;
}
module_init(init_physmap);
module_exit(cleanup_physmap);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("Generic configurable MTD map driver");

93
drivers/mtd/maps/pnc2000.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,93 @@
/*
* pnc2000.c - mapper for Photron PNC-2000 board.
*
* Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
*
* This code is GPL
*
* $Id: pnc2000.c,v 1.17 2004/11/16 18:29:02 dwmw2 Exp $
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#define WINDOW_ADDR 0xbf000000
#define WINDOW_SIZE 0x00400000
/*
* MAP DRIVER STUFF
*/
static struct map_info pnc_map = {
.name = "PNC-2000",
.size = WINDOW_SIZE,
.bankwidth = 4,
.phys = 0xFFFFFFFF,
.virt = (void __iomem *)WINDOW_ADDR,
};
/*
* MTD 'PARTITIONING' STUFF
*/
static struct mtd_partition pnc_partitions[3] = {
{
.name = "PNC-2000 boot firmware",
.size = 0x20000,
.offset = 0
},
{
.name = "PNC-2000 kernel",
.size = 0x1a0000,
.offset = 0x20000
},
{
.name = "PNC-2000 filesystem",
.size = 0x240000,
.offset = 0x1c0000
}
};
/*
* This is the master MTD device for which all the others are just
* auto-relocating aliases.
*/
static struct mtd_info *mymtd;
static int __init init_pnc2000(void)
{
printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
simple_map_init(&pnc_map);
mymtd = do_map_probe("cfi_probe", &pnc_map);
if (mymtd) {
mymtd->owner = THIS_MODULE;
return add_mtd_partitions(mymtd, pnc_partitions, 3);
}
return -ENXIO;
}
static void __exit cleanup_pnc2000(void)
{
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
}
module_init(init_pnc2000);
module_exit(cleanup_pnc2000);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Crossnet Co. <info@crossnet.co.jp>");
MODULE_DESCRIPTION("MTD map driver for Photron PNC-2000 board");

169
drivers/mtd/maps/redwood.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,169 @@
/*
* $Id: redwood.c,v 1.10 2004/11/04 13:24:15 gleixner Exp $
*
* drivers/mtd/maps/redwood.c
*
* FLASH map for the IBM Redwood 4/5/6 boards.
*
* Author: MontaVista Software, Inc. <source@mvista.com>
*
* 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#if !defined (CONFIG_REDWOOD_6)
#define WINDOW_ADDR 0xffc00000
#define WINDOW_SIZE 0x00400000
#define RW_PART0_OF 0
#define RW_PART0_SZ 0x10000
#define RW_PART1_OF RW_PART0_SZ
#define RW_PART1_SZ 0x200000 - 0x10000
#define RW_PART2_OF 0x200000
#define RW_PART2_SZ 0x10000
#define RW_PART3_OF 0x210000
#define RW_PART3_SZ 0x200000 - (0x10000 + 0x20000)
#define RW_PART4_OF 0x3e0000
#define RW_PART4_SZ 0x20000
static struct mtd_partition redwood_flash_partitions[] = {
{
.name = "Redwood OpenBIOS Vital Product Data",
.offset = RW_PART0_OF,
.size = RW_PART0_SZ,
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{
.name = "Redwood kernel",
.offset = RW_PART1_OF,
.size = RW_PART1_SZ
},
{
.name = "Redwood OpenBIOS non-volatile storage",
.offset = RW_PART2_OF,
.size = RW_PART2_SZ,
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{
.name = "Redwood filesystem",
.offset = RW_PART3_OF,
.size = RW_PART3_SZ
},
{
.name = "Redwood OpenBIOS",
.offset = RW_PART4_OF,
.size = RW_PART4_SZ,
.mask_flags = MTD_WRITEABLE /* force read-only */
}
};
#else /* CONFIG_REDWOOD_6 */
/* FIXME: the window is bigger - armin */
#define WINDOW_ADDR 0xff800000
#define WINDOW_SIZE 0x00800000
#define RW_PART0_OF 0
#define RW_PART0_SZ 0x400000 /* 4 MiB data */
#define RW_PART1_OF RW_PART0_OF + RW_PART0_SZ
#define RW_PART1_SZ 0x10000 /* 64K VPD */
#define RW_PART2_OF RW_PART1_OF + RW_PART1_SZ
#define RW_PART2_SZ 0x400000 - (0x10000 + 0x20000)
#define RW_PART3_OF RW_PART2_OF + RW_PART2_SZ
#define RW_PART3_SZ 0x20000
static struct mtd_partition redwood_flash_partitions[] = {
{
.name = "Redwood filesystem",
.offset = RW_PART0_OF,
.size = RW_PART0_SZ
},
{
.name = "Redwood OpenBIOS Vital Product Data",
.offset = RW_PART1_OF,
.size = RW_PART1_SZ,
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{
.name = "Redwood kernel",
.offset = RW_PART2_OF,
.size = RW_PART2_SZ
},
{
.name = "Redwood OpenBIOS",
.offset = RW_PART3_OF,
.size = RW_PART3_SZ,
.mask_flags = MTD_WRITEABLE /* force read-only */
}
};
#endif /* CONFIG_REDWOOD_6 */
struct map_info redwood_flash_map = {
.name = "IBM Redwood",
.size = WINDOW_SIZE,
.bankwidth = 2,
.phys = WINDOW_ADDR,
};
#define NUM_REDWOOD_FLASH_PARTITIONS \
(sizeof(redwood_flash_partitions)/sizeof(redwood_flash_partitions[0]))
static struct mtd_info *redwood_mtd;
int __init init_redwood_flash(void)
{
printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n",
WINDOW_SIZE, WINDOW_ADDR);
redwood_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!redwood_flash_map.virt) {
printk("init_redwood_flash: failed to ioremap\n");
return -EIO;
}
simple_map_init(&redwood_flash_map);
redwood_mtd = do_map_probe("cfi_probe",&redwood_flash_map);
if (redwood_mtd) {
redwood_mtd->owner = THIS_MODULE;
return add_mtd_partitions(redwood_mtd,
redwood_flash_partitions,
NUM_REDWOOD_FLASH_PARTITIONS);
}
return -ENXIO;
}
static void __exit cleanup_redwood_flash(void)
{
if (redwood_mtd) {
del_mtd_partitions(redwood_mtd);
/* moved iounmap after map_destroy - armin */
map_destroy(redwood_mtd);
iounmap((void *)redwood_flash_map.virt);
}
}
module_init(init_redwood_flash);
module_exit(cleanup_redwood_flash);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("MontaVista Software <source@mvista.com>");
MODULE_DESCRIPTION("MTD map driver for the IBM Redwood reference boards");

66
drivers/mtd/maps/rpxlite.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,66 @@
/*
* $Id: rpxlite.c,v 1.22 2004/11/04 13:24:15 gleixner Exp $
*
* Handle mapping of the flash on the RPX Lite and CLLF boards
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#define WINDOW_ADDR 0xfe000000
#define WINDOW_SIZE 0x800000
static struct mtd_info *mymtd;
static struct map_info rpxlite_map = {
.name = "RPX",
.size = WINDOW_SIZE,
.bankwidth = 4,
.phys = WINDOW_ADDR,
};
int __init init_rpxlite(void)
{
printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR);
rpxlite_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
if (!rpxlite_map.virt) {
printk("Failed to ioremap\n");
return -EIO;
}
simple_map_init(&rpxlite_map);
mymtd = do_map_probe("cfi_probe", &rpxlite_map);
if (mymtd) {
mymtd->owner = THIS_MODULE;
add_mtd_device(mymtd);
return 0;
}
iounmap((void *)rpxlite_map.virt);
return -ENXIO;
}
static void __exit cleanup_rpxlite(void)
{
if (mymtd) {
del_mtd_device(mymtd);
map_destroy(mymtd);
}
if (rpxlite_map.virt) {
iounmap((void *)rpxlite_map.virt);
rpxlite_map.virt = 0;
}
}
module_init(init_rpxlite);
module_exit(cleanup_rpxlite);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arnold Christensen <AKC@pel.dk>");
MODULE_DESCRIPTION("MTD map driver for RPX Lite and CLLF boards");

453
drivers/mtd/maps/sa1100-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,453 @@
/*
* Flash memory access on SA11x0 based devices
*
* (C) 2000 Nicolas Pitre <nico@cam.org>
*
* $Id: sa1100-flash.c,v 1.47 2004/11/01 13:44:36 rmk Exp $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/concat.h>
#include <asm/mach-types.h>
#include <asm/io.h>
#include <asm/sizes.h>
#include <asm/mach/flash.h>
#if 0
/*
* This is here for documentation purposes only - until these people
* submit their machine types. It will be gone January 2005.
*/
static struct mtd_partition consus_partitions[] = {
{
.name = "Consus boot firmware",
.offset = 0,
.size = 0x00040000,
.mask_flags = MTD_WRITABLE, /* force read-only */
}, {
.name = "Consus kernel",
.offset = 0x00040000,
.size = 0x00100000,
.mask_flags = 0,
}, {
.name = "Consus disk",
.offset = 0x00140000,
/* The rest (up to 16M) for jffs. We could put 0 and
make it find the size automatically, but right now
i have 32 megs. jffs will use all 32 megs if given
the chance, and this leads to horrible problems
when you try to re-flash the image because blob
won't erase the whole partition. */
.size = 0x01000000 - 0x00140000,
.mask_flags = 0,
}, {
/* this disk is a secondary disk, which can be used as
needed, for simplicity, make it the size of the other
consus partition, although realistically it could be
the remainder of the disk (depending on the file
system used) */
.name = "Consus disk2",
.offset = 0x01000000,
.size = 0x01000000 - 0x00140000,
.mask_flags = 0,
}
};
/* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */
static struct mtd_partition frodo_partitions[] =
{
{
.name = "bootloader",
.size = 0x00040000,
.offset = 0x00000000,
.mask_flags = MTD_WRITEABLE
}, {
.name = "bootloader params",
.size = 0x00040000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE
}, {
.name = "kernel",
.size = 0x00100000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE
}, {
.name = "ramdisk",
.size = 0x00400000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE
}, {
.name = "file system",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND
}
};
static struct mtd_partition jornada56x_partitions[] = {
{
.name = "bootldr",
.size = 0x00040000,
.offset = 0,
.mask_flags = MTD_WRITEABLE,
}, {
.name = "rootfs",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND,
}
};
static void jornada56x_set_vpp(int vpp)
{
if (vpp)
GPSR = GPIO_GPIO26;
else
GPCR = GPIO_GPIO26;
GPDR |= GPIO_GPIO26;
}
/*
* Machine Phys Size set_vpp
* Consus : SA1100_CS0_PHYS SZ_32M
* Frodo : SA1100_CS0_PHYS SZ_32M
* Jornada56x: SA1100_CS0_PHYS SZ_32M jornada56x_set_vpp
*/
#endif
struct sa_subdev_info {
char name[16];
struct map_info map;
struct mtd_info *mtd;
struct flash_platform_data *data;
};
struct sa_info {
struct mtd_partition *parts;
struct mtd_info *mtd;
int num_subdev;
struct sa_subdev_info subdev[0];
};
static void sa1100_set_vpp(struct map_info *map, int on)
{
struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map);
subdev->data->set_vpp(on);
}
static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
{
if (subdev->mtd)
map_destroy(subdev->mtd);
if (subdev->map.virt)
iounmap(subdev->map.virt);
release_mem_region(subdev->map.phys, subdev->map.size);
}
static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *res)
{
unsigned long phys;
unsigned int size;
int ret;
phys = res->start;
size = res->end - phys + 1;
/*
* Retrieve the bankwidth from the MSC registers.
* We currently only implement CS0 and CS1 here.
*/
switch (phys) {
default:
printk(KERN_WARNING "SA1100 flash: unknown base address "
"0x%08lx, assuming CS0\n", phys);
case SA1100_CS0_PHYS:
subdev->map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
break;
case SA1100_CS1_PHYS:
subdev->map.bankwidth = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4;
break;
}
if (!request_mem_region(phys, size, subdev->name)) {
ret = -EBUSY;
goto out;
}
if (subdev->data->set_vpp)
subdev->map.set_vpp = sa1100_set_vpp;
subdev->map.phys = phys;
subdev->map.size = size;
subdev->map.virt = ioremap(phys, size);
if (!subdev->map.virt) {
ret = -ENOMEM;
goto err;
}
simple_map_init(&subdev->map);
/*
* Now let's probe for the actual flash. Do it here since
* specific machine settings might have been set above.
*/
subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map);
if (subdev->mtd == NULL) {
ret = -ENXIO;
goto err;
}
subdev->mtd->owner = THIS_MODULE;
printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
"%d-bit\n", phys, subdev->mtd->size >> 20,
subdev->map.bankwidth * 8);
return 0;
err:
sa1100_destroy_subdev(subdev);
out:
return ret;
}
static void sa1100_destroy(struct sa_info *info)
{
int i;
if (info->mtd) {
del_mtd_partitions(info->mtd);
#ifdef CONFIG_MTD_CONCAT
if (info->mtd != info->subdev[0].mtd)
mtd_concat_destroy(info->mtd);
#endif
}
if (info->parts)
kfree(info->parts);
for (i = info->num_subdev - 1; i >= 0; i--)
sa1100_destroy_subdev(&info->subdev[i]);
kfree(info);
}
static struct sa_info *__init
sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash)
{
struct sa_info *info;
int nr, size, i, ret = 0;
/*
* Count number of devices.
*/
for (nr = 0; ; nr++)
if (!platform_get_resource(pdev, IORESOURCE_MEM, nr))
break;
if (nr == 0) {
ret = -ENODEV;
goto out;
}
size = sizeof(struct sa_info) + sizeof(struct sa_subdev_info) * nr;
/*
* Allocate the map_info structs in one go.
*/
info = kmalloc(size, GFP_KERNEL);
if (!info) {
ret = -ENOMEM;
goto out;
}
memset(info, 0, size);
/*
* Claim and then map the memory regions.
*/
for (i = 0; i < nr; i++) {
struct sa_subdev_info *subdev = &info->subdev[i];
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
break;
subdev->map.name = subdev->name;
sprintf(subdev->name, "sa1100-%d", i);
subdev->data = flash;
ret = sa1100_probe_subdev(subdev, res);
if (ret)
break;
}
info->num_subdev = i;
/*
* ENXIO is special. It means we didn't find a chip when we probed.
*/
if (ret != 0 && !(ret == -ENXIO && info->num_subdev > 0))
goto err;
/*
* If we found one device, don't bother with concat support. If
* we found multiple devices, use concat if we have it available,
* otherwise fail. Either way, it'll be called "sa1100".
*/
if (info->num_subdev == 1) {
strcpy(info->subdev[0].name, "sa1100");
info->mtd = info->subdev[0].mtd;
ret = 0;
} else if (info->num_subdev > 1) {
#ifdef CONFIG_MTD_CONCAT
struct mtd_info *cdev[nr];
/*
* We detected multiple devices. Concatenate them together.
*/
for (i = 0; i < info->num_subdev; i++)
cdev[i] = info->subdev[i].mtd;
info->mtd = mtd_concat_create(cdev, info->num_subdev,
"sa1100");
if (info->mtd == NULL)
ret = -ENXIO;
#else
printk(KERN_ERR "SA1100 flash: multiple devices "
"found but MTD concat support disabled.\n");
ret = -ENXIO;
#endif
}
if (ret == 0)
return info;
err:
sa1100_destroy(info);
out:
return ERR_PTR(ret);
}
static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
static int __init sa1100_mtd_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct flash_platform_data *flash = pdev->dev.platform_data;
struct mtd_partition *parts;
const char *part_type = NULL;
struct sa_info *info;
int err, nr_parts = 0;
if (!flash)
return -ENODEV;
info = sa1100_setup_mtd(pdev, flash);
if (IS_ERR(info)) {
err = PTR_ERR(info);
goto out;
}
/*
* Partition selection stuff.
*/
#ifdef CONFIG_MTD_PARTITIONS
nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
if (nr_parts > 0) {
info->parts = parts;
part_type = "dynamic";
} else
#endif
{
parts = flash->parts;
nr_parts = flash->nr_parts;
part_type = "static";
}
if (nr_parts == 0) {
printk(KERN_NOTICE "SA1100 flash: no partition info "
"available, registering whole flash\n");
add_mtd_device(info->mtd);
} else {
printk(KERN_NOTICE "SA1100 flash: using %s partition "
"definition\n", part_type);
add_mtd_partitions(info->mtd, parts, nr_parts);
}
dev_set_drvdata(dev, info);
err = 0;
out:
return err;
}
static int __exit sa1100_mtd_remove(struct device *dev)
{
struct sa_info *info = dev_get_drvdata(dev);
dev_set_drvdata(dev, NULL);
sa1100_destroy(info);
return 0;
}
#ifdef CONFIG_PM
static int sa1100_mtd_suspend(struct device *dev, u32 state, u32 level)
{
struct sa_info *info = dev_get_drvdata(dev);
int ret = 0;
if (info && level == SUSPEND_SAVE_STATE)
ret = info->mtd->suspend(info->mtd);
return ret;
}
static int sa1100_mtd_resume(struct device *dev, u32 level)
{
struct sa_info *info = dev_get_drvdata(dev);
if (info && level == RESUME_RESTORE_STATE)
info->mtd->resume(info->mtd);
return 0;
}
#else
#define sa1100_mtd_suspend NULL
#define sa1100_mtd_resume NULL
#endif
static struct device_driver sa1100_mtd_driver = {
.name = "flash",
.bus = &platform_bus_type,
.probe = sa1100_mtd_probe,
.remove = __exit_p(sa1100_mtd_remove),
.suspend = sa1100_mtd_suspend,
.resume = sa1100_mtd_resume,
};
static int __init sa1100_mtd_init(void)
{
return driver_register(&sa1100_mtd_driver);
}
static void __exit sa1100_mtd_exit(void)
{
driver_unregister(&sa1100_mtd_driver);
}
module_init(sa1100_mtd_init);
module_exit(sa1100_mtd_exit);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("SA1100 CFI map driver");
MODULE_LICENSE("GPL");

247
drivers/mtd/maps/sbc8240.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,247 @@
/*
* Handle mapping of the flash memory access routines on the SBC8240 board.
*
* Carolyn Smith, Tektronix, Inc.
*
* This code is GPLed
*
* $Id: sbc8240.c,v 1.4 2004/07/12 22:38:29 dwmw2 Exp $
*
*/
/*
* The SBC8240 has 2 flash banks.
* Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors.
* It contains the U-Boot code (7 sectors) and the environment (1 sector).
* Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector,
* 2 x 8 KiB sectors, 1 x 16 KiB sectors.
* Both parts are JEDEC compatible.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/cfi.h>
#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
#endif
#define DEBUG
#ifdef DEBUG
# define debugk(fmt,args...) printk(fmt ,##args)
#else
# define debugk(fmt,args...)
#endif
#define WINDOW_ADDR0 0xFFF00000 /* 512 KiB */
#define WINDOW_SIZE0 0x00080000
#define BUSWIDTH0 1
#define WINDOW_ADDR1 0xFF000000 /* 4 MiB */
#define WINDOW_SIZE1 0x00400000
#define BUSWIDTH1 8
#define MSG_PREFIX "sbc8240:" /* prefix for our printk()'s */
#define MTDID "sbc8240-%d" /* for mtdparts= partitioning */
static struct map_info sbc8240_map[2] = {
{
.name = "sbc8240 Flash Bank #0",
.size = WINDOW_SIZE0,
.bankwidth = BUSWIDTH0,
},
{
.name = "sbc8240 Flash Bank #1",
.size = WINDOW_SIZE1,
.bankwidth = BUSWIDTH1,
}
};
#define NUM_FLASH_BANKS (sizeof(sbc8240_map) / sizeof(struct map_info))
/*
* The following defines the partition layout of SBC8240 boards.
*
* See include/linux/mtd/partitions.h for definition of the
* mtd_partition structure.
*
* The *_max_flash_size is the maximum possible mapped flash size
* which is not necessarily the actual flash size. It must correspond
* to the value specified in the mapping definition defined by the
* "struct map_desc *_io_desc" for the corresponding machine.
*/
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition sbc8240_uboot_partitions [] = {
/* Bank 0 */
{
.name = "U-boot", /* U-Boot Firmware */
.offset = 0,
.size = 0x00070000, /* 7 x 64 KiB sectors */
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
{
.name = "environment", /* U-Boot environment */
.offset = 0x00070000,
.size = 0x00010000, /* 1 x 64 KiB sector */
},
};
static struct mtd_partition sbc8240_fs_partitions [] = {
{
.name = "jffs", /* JFFS filesystem */
.offset = 0,
.size = 0x003C0000, /* 4 * 15 * 64KiB */
},
{
.name = "tmp32",
.offset = 0x003C0000,
.size = 0x00020000, /* 4 * 32KiB */
},
{
.name = "tmp8a",
.offset = 0x003E0000,
.size = 0x00008000, /* 4 * 8KiB */
},
{
.name = "tmp8b",
.offset = 0x003E8000,
.size = 0x00008000, /* 4 * 8KiB */
},
{
.name = "tmp16",
.offset = 0x003F0000,
.size = 0x00010000, /* 4 * 16KiB */
}
};
#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
/* trivial struct to describe partition information */
struct mtd_part_def
{
int nums;
unsigned char *type;
struct mtd_partition* mtd_part;
};
static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS];
static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS];
#endif /* CONFIG_MTD_PARTITIONS */
int __init init_sbc8240_mtd (void)
{
static struct _cjs {
u_long addr;
u_long size;
} pt[NUM_FLASH_BANKS] = {
{
.addr = WINDOW_ADDR0,
.size = WINDOW_SIZE0
},
{
.addr = WINDOW_ADDR1,
.size = WINDOW_SIZE1
},
};
int devicesfound = 0;
int i;
for (i = 0; i < NUM_FLASH_BANKS; i++) {
printk (KERN_NOTICE MSG_PREFIX
"Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr);
sbc8240_map[i].map_priv_1 =
(unsigned long) ioremap (pt[i].addr, pt[i].size);
if (!sbc8240_map[i].map_priv_1) {
printk (MSG_PREFIX "failed to ioremap\n");
return -EIO;
}
simple_map_init(&sbc8240_mtd[i]);
sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]);
if (sbc8240_mtd[i]) {
sbc8240_mtd[i]->module = THIS_MODULE;
devicesfound++;
}
}
if (!devicesfound) {
printk(KERN_NOTICE MSG_PREFIX
"No suppported flash chips found!\n");
return -ENXIO;
}
#ifdef CONFIG_MTD_PARTITIONS
sbc8240_part_banks[0].mtd_part = sbc8240_uboot_partitions;
sbc8240_part_banks[0].type = "static image";
sbc8240_part_banks[0].nums = NB_OF(sbc8240_uboot_partitions);
sbc8240_part_banks[1].mtd_part = sbc8240_fs_partitions;
sbc8240_part_banks[1].type = "static file system";
sbc8240_part_banks[1].nums = NB_OF(sbc8240_fs_partitions);
for (i = 0; i < NUM_FLASH_BANKS; i++) {
if (!sbc8240_mtd[i]) continue;
if (sbc8240_part_banks[i].nums == 0) {
printk (KERN_NOTICE MSG_PREFIX
"No partition info available, registering whole device\n");
add_mtd_device(sbc8240_mtd[i]);
} else {
printk (KERN_NOTICE MSG_PREFIX
"Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name);
add_mtd_partitions (sbc8240_mtd[i],
sbc8240_part_banks[i].mtd_part,
sbc8240_part_banks[i].nums);
}
}
#else
printk(KERN_NOTICE MSG_PREFIX
"Registering %d flash banks at once\n", devicesfound);
for (i = 0; i < devicesfound; i++) {
add_mtd_device(sbc8240_mtd[i]);
}
#endif /* CONFIG_MTD_PARTITIONS */
return devicesfound == 0 ? -ENXIO : 0;
}
static void __exit cleanup_sbc8240_mtd (void)
{
int i;
for (i = 0; i < NUM_FLASH_BANKS; i++) {
if (sbc8240_mtd[i]) {
del_mtd_device (sbc8240_mtd[i]);
map_destroy (sbc8240_mtd[i]);
}
if (sbc8240_map[i].map_priv_1) {
iounmap ((void *) sbc8240_map[i].map_priv_1);
sbc8240_map[i].map_priv_1 = 0;
}
}
}
module_init (init_sbc8240_mtd);
module_exit (cleanup_sbc8240_mtd);
MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("Carolyn Smith <carolyn.smith@tektronix.com>");
MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards");

239
drivers/mtd/maps/sbc_gxx.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,239 @@
/* sbc_gxx.c -- MTD map driver for Arcom Control Systems SBC-MediaGX,
SBC-GXm and SBC-GX1 series boards.
Copyright (C) 2001 Arcom Control System Ltd
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
$Id: sbc_gxx.c,v 1.33 2004/11/28 09:40:40 dwmw2 Exp $
The SBC-MediaGX / SBC-GXx has up to 16 MiB of
Intel StrataFlash (28F320/28F640) in x8 mode.
This driver uses the CFI probe and Intel Extended Command Set drivers.
The flash is accessed as follows:
16 KiB memory window at 0xdc000-0xdffff
Two IO address locations for paging
0x258
bit 0-7: address bit 14-21
0x259
bit 0-1: address bit 22-23
bit 7: 0 - reset/powered down
1 - device enabled
The single flash device is divided into 3 partition which appear as
separate MTD devices.
25/04/2001 AJL (Arcom) Modified signon strings and partition sizes
(to support bzImages up to 638KiB-ish)
*/
// Includes
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
// Defines
// - Hardware specific
#define WINDOW_START 0xdc000
/* Number of bits in offset. */
#define WINDOW_SHIFT 14
#define WINDOW_LENGTH (1 << WINDOW_SHIFT)
/* The bits for the offset into the window. */
#define WINDOW_MASK (WINDOW_LENGTH-1)
#define PAGE_IO 0x258
#define PAGE_IO_SIZE 2
/* bit 7 of 0x259 must be 1 to enable device. */
#define DEVICE_ENABLE 0x8000
// - Flash / Partition sizing
#define MAX_SIZE_KiB 16384
#define BOOT_PARTITION_SIZE_KiB 768
#define DATA_PARTITION_SIZE_KiB 1280
#define APP_PARTITION_SIZE_KiB 6144
// Globals
static volatile int page_in_window = -1; // Current page in window.
static void __iomem *iomapadr;
static DEFINE_SPINLOCK(sbc_gxx_spin);
/* partition_info gives details on the logical partitions that the split the
* single flash device into. If the size if zero we use up to the end of the
* device. */
static struct mtd_partition partition_info[]={
{ .name = "SBC-GXx flash boot partition",
.offset = 0,
.size = BOOT_PARTITION_SIZE_KiB*1024 },
{ .name = "SBC-GXx flash data partition",
.offset = BOOT_PARTITION_SIZE_KiB*1024,
.size = (DATA_PARTITION_SIZE_KiB)*1024 },
{ .name = "SBC-GXx flash application partition",
.offset = (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 }
};
#define NUM_PARTITIONS 3
static inline void sbc_gxx_page(struct map_info *map, unsigned long ofs)
{
unsigned long page = ofs >> WINDOW_SHIFT;
if( page!=page_in_window ) {
outw( page | DEVICE_ENABLE, PAGE_IO );
page_in_window = page;
}
}
static map_word sbc_gxx_read8(struct map_info *map, unsigned long ofs)
{
map_word ret;
spin_lock(&sbc_gxx_spin);
sbc_gxx_page(map, ofs);
ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK));
spin_unlock(&sbc_gxx_spin);
return ret;
}
static void sbc_gxx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
while(len) {
unsigned long thislen = len;
if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
spin_lock(&sbc_gxx_spin);
sbc_gxx_page(map, from);
memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen);
spin_unlock(&sbc_gxx_spin);
to += thislen;
from += thislen;
len -= thislen;
}
}
static void sbc_gxx_write8(struct map_info *map, map_word d, unsigned long adr)
{
spin_lock(&sbc_gxx_spin);
sbc_gxx_page(map, adr);
writeb(d.x[0], iomapadr + (adr & WINDOW_MASK));
spin_unlock(&sbc_gxx_spin);
}
static void sbc_gxx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
while(len) {
unsigned long thislen = len;
if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
spin_lock(&sbc_gxx_spin);
sbc_gxx_page(map, to);
memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen);
spin_unlock(&sbc_gxx_spin);
to += thislen;
from += thislen;
len -= thislen;
}
}
static struct map_info sbc_gxx_map = {
.name = "SBC-GXx flash",
.phys = NO_XIP,
.size = MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount
of flash so the cfi probe routines find all
the chips */
.bankwidth = 1,
.read = sbc_gxx_read8,
.copy_from = sbc_gxx_copy_from,
.write = sbc_gxx_write8,
.copy_to = sbc_gxx_copy_to
};
/* MTD device for all of the flash. */
static struct mtd_info *all_mtd;
static void cleanup_sbc_gxx(void)
{
if( all_mtd ) {
del_mtd_partitions( all_mtd );
map_destroy( all_mtd );
}
iounmap(iomapadr);
release_region(PAGE_IO,PAGE_IO_SIZE);
}
static int __init init_sbc_gxx(void)
{
iomapadr = ioremap(WINDOW_START, WINDOW_LENGTH);
if (!iomapadr) {
printk( KERN_ERR"%s: failed to ioremap memory region\n",
sbc_gxx_map.name );
return -EIO;
}
if (!request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash")) {
printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n",
sbc_gxx_map.name,
PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 );
iounmap(iomapadr);
return -EAGAIN;
}
printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n",
sbc_gxx_map.name,
PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1,
WINDOW_START, WINDOW_START+WINDOW_LENGTH-1 );
/* Probe for chip. */
all_mtd = do_map_probe( "cfi_probe", &sbc_gxx_map );
if( !all_mtd ) {
cleanup_sbc_gxx();
return -ENXIO;
}
all_mtd->owner = THIS_MODULE;
/* Create MTD devices for each partition. */
add_mtd_partitions(all_mtd, partition_info, NUM_PARTITIONS );
return 0;
}
module_init(init_sbc_gxx);
module_exit(cleanup_sbc_gxx);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arcom Control Systems Ltd.");
MODULE_DESCRIPTION("MTD map driver for SBC-GXm and SBC-GX1 series boards");

304
drivers/mtd/maps/sc520cdp.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,304 @@
/* sc520cdp.c -- MTD map driver for AMD SC520 Customer Development Platform
*
* Copyright (C) 2001 Sysgo Real-Time Solutions GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* $Id: sc520cdp.c,v 1.21 2004/12/13 10:27:08 dedekind Exp $
*
*
* The SC520CDP is an evaluation board for the Elan SC520 processor available
* from AMD. It has two banks of 32-bit Flash ROM, each 8 Megabytes in size,
* and up to 512 KiB of 8-bit DIL Flash ROM.
* For details see http://www.amd.com/products/epd/desiging/evalboards/18.elansc520/520_cdp_brief/index.html
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/concat.h>
/*
** The Embedded Systems BIOS decodes the first FLASH starting at
** 0x8400000. This is a *terrible* place for it because accessing
** the flash at this location causes the A22 address line to be high
** (that's what 0x8400000 binary's ought to be). But this is the highest
** order address line on the raw flash devices themselves!!
** This causes the top HALF of the flash to be accessed first. Beyond
** the physical limits of the flash, the flash chip aliases over (to
** 0x880000 which causes the bottom half to be accessed. This splits the
** flash into two and inverts it! If you then try to access this from another
** program that does NOT do this insanity, then you *will* access the
** first half of the flash, but not find what you expect there. That
** stuff is in the *second* half! Similarly, the address used by the
** BIOS for the second FLASH bank is also quite a bad choice.
** If REPROGRAM_PAR is defined below (the default), then this driver will
** choose more useful addresses for the FLASH banks by reprogramming the
** responsible PARxx registers in the SC520's MMCR region. This will
** cause the settings to be incompatible with the BIOS's settings, which
** shouldn't be a problem since you are running Linux, (i.e. the BIOS is
** not much use anyway). However, if you need to be compatible with
** the BIOS for some reason, just undefine REPROGRAM_PAR.
*/
#define REPROGRAM_PAR
#ifdef REPROGRAM_PAR
/* These are the addresses we want.. */
#define WINDOW_ADDR_0 0x08800000
#define WINDOW_ADDR_1 0x09000000
#define WINDOW_ADDR_2 0x09800000
/* .. and these are the addresses the BIOS gives us */
#define WINDOW_ADDR_0_BIOS 0x08400000
#define WINDOW_ADDR_1_BIOS 0x08c00000
#define WINDOW_ADDR_2_BIOS 0x09400000
#else
#define WINDOW_ADDR_0 0x08400000
#define WINDOW_ADDR_1 0x08C00000
#define WINDOW_ADDR_2 0x09400000
#endif
#define WINDOW_SIZE_0 0x00800000
#define WINDOW_SIZE_1 0x00800000
#define WINDOW_SIZE_2 0x00080000
static struct map_info sc520cdp_map[] = {
{
.name = "SC520CDP Flash Bank #0",
.size = WINDOW_SIZE_0,
.bankwidth = 4,
.phys = WINDOW_ADDR_0
},
{
.name = "SC520CDP Flash Bank #1",
.size = WINDOW_SIZE_1,
.bankwidth = 4,
.phys = WINDOW_ADDR_1
},
{
.name = "SC520CDP DIL Flash",
.size = WINDOW_SIZE_2,
.bankwidth = 1,
.phys = WINDOW_ADDR_2
},
};
#define NUM_FLASH_BANKS (sizeof(sc520cdp_map)/sizeof(struct map_info))
static struct mtd_info *mymtd[NUM_FLASH_BANKS];
static struct mtd_info *merged_mtd;
#ifdef REPROGRAM_PAR
/*
** The SC520 MMCR (memory mapped control register) region resides
** at 0xFFFEF000. The 16 Programmable Address Region (PAR) registers
** are at offset 0x88 in the MMCR:
*/
#define SC520_MMCR_BASE 0xFFFEF000
#define SC520_MMCR_EXTENT 0x1000
#define SC520_PAR(x) ((0x88/sizeof(unsigned long)) + (x))
#define NUM_SC520_PAR 16 /* total number of PAR registers */
/*
** The highest three bits in a PAR register determine what target
** device is controlled by this PAR. Here, only ROMCS? and BOOTCS
** devices are of interest.
*/
#define SC520_PAR_BOOTCS (0x4<<29)
#define SC520_PAR_ROMCS0 (0x5<<29)
#define SC520_PAR_ROMCS1 (0x6<<29)
#define SC520_PAR_TRGDEV (0x7<<29)
/*
** Bits 28 thru 26 determine some attributes for the
** region controlled by the PAR. (We only use non-cacheable)
*/
#define SC520_PAR_WRPROT (1<<26) /* write protected */
#define SC520_PAR_NOCACHE (1<<27) /* non-cacheable */
#define SC520_PAR_NOEXEC (1<<28) /* code execution denied */
/*
** Bit 25 determines the granularity: 4K or 64K
*/
#define SC520_PAR_PG_SIZ4 (0<<25)
#define SC520_PAR_PG_SIZ64 (1<<25)
/*
** Build a value to be written into a PAR register.
** We only need ROM entries, 64K page size:
*/
#define SC520_PAR_ENTRY(trgdev, address, size) \
((trgdev) | SC520_PAR_NOCACHE | SC520_PAR_PG_SIZ64 | \
(address) >> 16 | (((size) >> 16) - 1) << 14)
struct sc520_par_table
{
unsigned long trgdev;
unsigned long new_par;
unsigned long default_address;
};
static struct sc520_par_table par_table[NUM_FLASH_BANKS] =
{
{ /* Flash Bank #0: selected by ROMCS0 */
SC520_PAR_ROMCS0,
SC520_PAR_ENTRY(SC520_PAR_ROMCS0, WINDOW_ADDR_0, WINDOW_SIZE_0),
WINDOW_ADDR_0_BIOS
},
{ /* Flash Bank #1: selected by ROMCS1 */
SC520_PAR_ROMCS1,
SC520_PAR_ENTRY(SC520_PAR_ROMCS1, WINDOW_ADDR_1, WINDOW_SIZE_1),
WINDOW_ADDR_1_BIOS
},
{ /* DIL (BIOS) Flash: selected by BOOTCS */
SC520_PAR_BOOTCS,
SC520_PAR_ENTRY(SC520_PAR_BOOTCS, WINDOW_ADDR_2, WINDOW_SIZE_2),
WINDOW_ADDR_2_BIOS
}
};
static void sc520cdp_setup_par(void)
{
volatile unsigned long __iomem *mmcr;
unsigned long mmcr_val;
int i, j;
/* map in SC520's MMCR area */
mmcr = ioremap_nocache(SC520_MMCR_BASE, SC520_MMCR_EXTENT);
if(!mmcr) { /* ioremap_nocache failed: skip the PAR reprogramming */
/* force physical address fields to BIOS defaults: */
for(i = 0; i < NUM_FLASH_BANKS; i++)
sc520cdp_map[i].phys = par_table[i].default_address;
return;
}
/*
** Find the PARxx registers that are reponsible for activating
** ROMCS0, ROMCS1 and BOOTCS. Reprogram each of these with a
** new value from the table.
*/
for(i = 0; i < NUM_FLASH_BANKS; i++) { /* for each par_table entry */
for(j = 0; j < NUM_SC520_PAR; j++) { /* for each PAR register */
mmcr_val = mmcr[SC520_PAR(j)];
/* if target device field matches, reprogram the PAR */
if((mmcr_val & SC520_PAR_TRGDEV) == par_table[i].trgdev)
{
mmcr[SC520_PAR(j)] = par_table[i].new_par;
break;
}
}
if(j == NUM_SC520_PAR)
{ /* no matching PAR found: try default BIOS address */
printk(KERN_NOTICE "Could not find PAR responsible for %s\n",
sc520cdp_map[i].name);
printk(KERN_NOTICE "Trying default address 0x%lx\n",
par_table[i].default_address);
sc520cdp_map[i].phys = par_table[i].default_address;
}
}
iounmap(mmcr);
}
#endif
static int __init init_sc520cdp(void)
{
int i, devices_found = 0;
#ifdef REPROGRAM_PAR
/* reprogram PAR registers so flash appears at the desired addresses */
sc520cdp_setup_par();
#endif
for (i = 0; i < NUM_FLASH_BANKS; i++) {
printk(KERN_NOTICE "SC520 CDP flash device: 0x%lx at 0x%lx\n",
sc520cdp_map[i].size, sc520cdp_map[i].phys);
sc520cdp_map[i].virt = ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size);
if (!sc520cdp_map[i].virt) {
printk("Failed to ioremap_nocache\n");
return -EIO;
}
simple_map_init(&sc520cdp_map[i]);
mymtd[i] = do_map_probe("cfi_probe", &sc520cdp_map[i]);
if(!mymtd[i])
mymtd[i] = do_map_probe("jedec_probe", &sc520cdp_map[i]);
if(!mymtd[i])
mymtd[i] = do_map_probe("map_rom", &sc520cdp_map[i]);
if (mymtd[i]) {
mymtd[i]->owner = THIS_MODULE;
++devices_found;
}
else {
iounmap(sc520cdp_map[i].virt);
}
}
if(devices_found >= 2) {
/* Combine the two flash banks into a single MTD device & register it: */
merged_mtd = mtd_concat_create(mymtd, 2, "SC520CDP Flash Banks #0 and #1");
if(merged_mtd)
add_mtd_device(merged_mtd);
}
if(devices_found == 3) /* register the third (DIL-Flash) device */
add_mtd_device(mymtd[2]);
return(devices_found ? 0 : -ENXIO);
}
static void __exit cleanup_sc520cdp(void)
{
int i;
if (merged_mtd) {
del_mtd_device(merged_mtd);
mtd_concat_destroy(merged_mtd);
}
if (mymtd[2])
del_mtd_device(mymtd[2]);
for (i = 0; i < NUM_FLASH_BANKS; i++) {
if (mymtd[i])
map_destroy(mymtd[i]);
if (sc520cdp_map[i].virt) {
iounmap(sc520cdp_map[i].virt);
sc520cdp_map[i].virt = NULL;
}
}
}
module_init(init_sc520cdp);
module_exit(cleanup_sc520cdp);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sysgo Real-Time Solutions GmbH");
MODULE_DESCRIPTION("MTD map driver for AMD SC520 Customer Development Platform");

256
drivers/mtd/maps/scb2_flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,256 @@
/*
* MTD map driver for BIOS Flash on Intel SCB2 boards
* $Id: scb2_flash.c,v 1.11 2004/11/28 09:40:40 dwmw2 Exp $
* Copyright (C) 2002 Sun Microsystems, Inc.
* Tim Hockin <thockin@sun.com>
*
* A few notes on this MTD map:
*
* This was developed with a small number of SCB2 boards to test on.
* Hopefully, Intel has not introducted too many unaccounted variables in the
* making of this board.
*
* The BIOS marks its own memory region as 'reserved' in the e820 map. We
* try to request it here, but if it fails, we carry on anyway.
*
* This is how the chip is attached, so said the schematic:
* * a 4 MiB (32 Mib) 16 bit chip
* * a 1 MiB memory region
* * A20 and A21 pulled up
* * D8-D15 ignored
* What this means is that, while we are addressing bytes linearly, we are
* really addressing words, and discarding the other byte. This means that
* the chip MUST BE at least 2 MiB. This also means that every block is
* actually half as big as the chip reports. It also means that accesses of
* logical address 0 hit higher-address sections of the chip, not physical 0.
* One can only hope that these 4MiB x16 chips were a lot cheaper than 1MiB x8
* chips.
*
* This driver assumes the chip is not write-protected by an external signal.
* As of the this writing, that is true, but may change, just to spite me.
*
* The actual BIOS layout has been mostly reverse engineered. Intel BIOS
* updates for this board include 10 related (*.bio - &.bi9) binary files and
* another separate (*.bbo) binary file. The 10 files are 64k of data + a
* small header. If the headers are stripped off, the 10 64k files can be
* concatenated into a 640k image. This is your BIOS image, proper. The
* separate .bbo file also has a small header. It is the 'Boot Block'
* recovery BIOS. Once the header is stripped, no further prep is needed.
* As best I can tell, the BIOS is arranged as such:
* offset 0x00000 to 0x4ffff (320k): unknown - SCSI BIOS, etc?
* offset 0x50000 to 0xeffff (640k): BIOS proper
* offset 0xf0000 ty 0xfffff (64k): Boot Block region
*
* Intel's BIOS update program flashes the BIOS and Boot Block in separate
* steps. Probably a wise thing to do.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/cfi.h>
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#define MODNAME "scb2_flash"
#define SCB2_ADDR 0xfff00000
#define SCB2_WINDOW 0x00100000
static void __iomem *scb2_ioaddr;
static struct mtd_info *scb2_mtd;
static struct map_info scb2_map = {
.name = "SCB2 BIOS Flash",
.size = 0,
.bankwidth = 1,
};
static int region_fail;
static int __devinit
scb2_fixup_mtd(struct mtd_info *mtd)
{
int i;
int done = 0;
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
/* barf if this doesn't look right */
if (cfi->cfiq->InterfaceDesc != 1) {
printk(KERN_ERR MODNAME ": unsupported InterfaceDesc: %#x\n",
cfi->cfiq->InterfaceDesc);
return -1;
}
/* I wasn't here. I didn't see. dwmw2. */
/* the chip is sometimes bigger than the map - what a waste */
mtd->size = map->size;
/*
* We only REALLY get half the chip, due to the way it is
* wired up - D8-D15 are tossed away. We read linear bytes,
* but in reality we are getting 1/2 of each 16-bit read,
* which LOOKS linear to us. Because CFI code accounts for
* things like lock/unlock/erase by eraseregions, we need to
* fudge them to reflect this. Erases go like this:
* * send an erase to an address
* * the chip samples the address and erases the block
* * add the block erasesize to the address and repeat
* -- the problem is that addresses are 16-bit addressable
* -- we end up erasing every-other block
*/
mtd->erasesize /= 2;
for (i = 0; i < mtd->numeraseregions; i++) {
struct mtd_erase_region_info *region = &mtd->eraseregions[i];
region->erasesize /= 2;
}
/*
* If the chip is bigger than the map, it is wired with the high
* address lines pulled up. This makes us access the top portion of
* the chip, so all our erase-region info is wrong. Start cutting from
* the bottom.
*/
for (i = 0; !done && i < mtd->numeraseregions; i++) {
struct mtd_erase_region_info *region = &mtd->eraseregions[i];
if (region->numblocks * region->erasesize > mtd->size) {
region->numblocks = (mtd->size / region->erasesize);
done = 1;
} else {
region->numblocks = 0;
}
region->offset = 0;
}
return 0;
}
/* CSB5's 'Function Control Register' has bits for decoding @ >= 0xffc00000 */
#define CSB5_FCR 0x41
#define CSB5_FCR_DECODE_ALL 0x0e
static int __devinit
scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent)
{
u8 reg;
/* enable decoding of the flash region in the south bridge */
pci_read_config_byte(dev, CSB5_FCR, &reg);
pci_write_config_byte(dev, CSB5_FCR, reg | CSB5_FCR_DECODE_ALL);
if (!request_mem_region(SCB2_ADDR, SCB2_WINDOW, scb2_map.name)) {
/*
* The BIOS seems to mark the flash region as 'reserved'
* in the e820 map. Warn and go about our business.
*/
printk(KERN_WARNING MODNAME
": warning - can't reserve rom window, continuing\n");
region_fail = 1;
}
/* remap the IO window (w/o caching) */
scb2_ioaddr = ioremap_nocache(SCB2_ADDR, SCB2_WINDOW);
if (!scb2_ioaddr) {
printk(KERN_ERR MODNAME ": Failed to ioremap window!\n");
if (!region_fail)
release_mem_region(SCB2_ADDR, SCB2_WINDOW);
return -ENOMEM;
}
scb2_map.phys = SCB2_ADDR;
scb2_map.virt = scb2_ioaddr;
scb2_map.size = SCB2_WINDOW;
simple_map_init(&scb2_map);
/* try to find a chip */
scb2_mtd = do_map_probe("cfi_probe", &scb2_map);
if (!scb2_mtd) {
printk(KERN_ERR MODNAME ": flash probe failed!\n");
iounmap(scb2_ioaddr);
if (!region_fail)
release_mem_region(SCB2_ADDR, SCB2_WINDOW);
return -ENODEV;
}
scb2_mtd->owner = THIS_MODULE;
if (scb2_fixup_mtd(scb2_mtd) < 0) {
del_mtd_device(scb2_mtd);
map_destroy(scb2_mtd);
iounmap(scb2_ioaddr);
if (!region_fail)
release_mem_region(SCB2_ADDR, SCB2_WINDOW);
return -ENODEV;
}
printk(KERN_NOTICE MODNAME ": chip size 0x%x at offset 0x%x\n",
scb2_mtd->size, SCB2_WINDOW - scb2_mtd->size);
add_mtd_device(scb2_mtd);
return 0;
}
static void __devexit
scb2_flash_remove(struct pci_dev *dev)
{
if (!scb2_mtd)
return;
/* disable flash writes */
if (scb2_mtd->lock)
scb2_mtd->lock(scb2_mtd, 0, scb2_mtd->size);
del_mtd_device(scb2_mtd);
map_destroy(scb2_mtd);
iounmap(scb2_ioaddr);
scb2_ioaddr = NULL;
if (!region_fail)
release_mem_region(SCB2_ADDR, SCB2_WINDOW);
pci_set_drvdata(dev, NULL);
}
static struct pci_device_id scb2_flash_pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_SERVERWORKS,
.device = PCI_DEVICE_ID_SERVERWORKS_CSB5,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID
},
{ 0, }
};
static struct pci_driver scb2_flash_driver = {
.name = "Intel SCB2 BIOS Flash",
.id_table = scb2_flash_pci_ids,
.probe = scb2_flash_probe,
.remove = __devexit_p(scb2_flash_remove),
};
static int __init
scb2_flash_init(void)
{
return pci_module_init(&scb2_flash_driver);
}
static void __exit
scb2_flash_exit(void)
{
pci_unregister_driver(&scb2_flash_driver);
}
module_init(scb2_flash_init);
module_exit(scb2_flash_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tim Hockin <thockin@sun.com>");
MODULE_DESCRIPTION("MTD map driver for Intel SCB2 BIOS Flash");
MODULE_DEVICE_TABLE(pci, scb2_flash_pci_ids);

233
drivers/mtd/maps/scx200_docflash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,233 @@
/* linux/drivers/mtd/maps/scx200_docflash.c
Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
$Id: scx200_docflash.c,v 1.10 2004/11/28 09:40:40 dwmw2 Exp $
National Semiconductor SCx200 flash mapped with DOCCS
*/
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/pci.h>
#include <linux/scx200.h>
#define NAME "scx200_docflash"
MODULE_AUTHOR("Christer Weinigel <wingel@hack.org>");
MODULE_DESCRIPTION("NatSemi SCx200 DOCCS Flash Driver");
MODULE_LICENSE("GPL");
static int probe = 0; /* Don't autoprobe */
static unsigned size = 0x1000000; /* 16 MiB the whole ISA address space */
static unsigned width = 8; /* Default to 8 bits wide */
static char *flashtype = "cfi_probe";
module_param(probe, int, 0);
MODULE_PARM_DESC(probe, "Probe for a BIOS mapping");
module_param(size, int, 0);
MODULE_PARM_DESC(size, "Size of the flash mapping");
module_param(width, int, 0);
MODULE_PARM_DESC(width, "Data width of the flash mapping (8/16)");
module_param(flashtype, charp, 0);
MODULE_PARM_DESC(flashtype, "Type of MTD probe to do");
static struct resource docmem = {
.flags = IORESOURCE_MEM,
.name = "NatSemi SCx200 DOCCS Flash",
};
static struct mtd_info *mymtd;
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition partition_info[] = {
{
.name = "DOCCS Boot kernel",
.offset = 0,
.size = 0xc0000
},
{
.name = "DOCCS Low BIOS",
.offset = 0xc0000,
.size = 0x40000
},
{
.name = "DOCCS File system",
.offset = 0x100000,
.size = ~0 /* calculate from flash size */
},
{
.name = "DOCCS High BIOS",
.offset = ~0, /* calculate from flash size */
.size = 0x80000
},
};
#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
#endif
static struct map_info scx200_docflash_map = {
.name = "NatSemi SCx200 DOCCS Flash",
};
static int __init init_scx200_docflash(void)
{
unsigned u;
unsigned base;
unsigned ctrl;
unsigned pmr;
struct pci_dev *bridge;
printk(KERN_DEBUG NAME ": NatSemi SCx200 DOCCS Flash Driver\n");
if ((bridge = pci_find_device(PCI_VENDOR_ID_NS,
PCI_DEVICE_ID_NS_SCx200_BRIDGE,
NULL)) == NULL)
return -ENODEV;
/* check that we have found the configuration block */
if (!scx200_cb_present())
return -ENODEV;
if (probe) {
/* Try to use the present flash mapping if any */
pci_read_config_dword(bridge, SCx200_DOCCS_BASE, &base);
pci_read_config_dword(bridge, SCx200_DOCCS_CTRL, &ctrl);
pmr = inl(scx200_cb_base + SCx200_PMR);
if (base == 0
|| (ctrl & 0x07000000) != 0x07000000
|| (ctrl & 0x0007ffff) == 0)
return -ENODEV;
size = ((ctrl&0x1fff)<<13) + (1<<13);
for (u = size; u > 1; u >>= 1)
;
if (u != 1)
return -ENODEV;
if (pmr & (1<<6))
width = 16;
else
width = 8;
docmem.start = base;
docmem.end = base + size;
if (request_resource(&iomem_resource, &docmem)) {
printk(KERN_ERR NAME ": unable to allocate memory for flash mapping\n");
return -ENOMEM;
}
} else {
for (u = size; u > 1; u >>= 1)
;
if (u != 1) {
printk(KERN_ERR NAME ": invalid size for flash mapping\n");
return -EINVAL;
}
if (width != 8 && width != 16) {
printk(KERN_ERR NAME ": invalid bus width for flash mapping\n");
return -EINVAL;
}
if (allocate_resource(&iomem_resource, &docmem,
size,
0xc0000000, 0xffffffff,
size, NULL, NULL)) {
printk(KERN_ERR NAME ": unable to allocate memory for flash mapping\n");
return -ENOMEM;
}
ctrl = 0x07000000 | ((size-1) >> 13);
printk(KERN_INFO "DOCCS BASE=0x%08lx, CTRL=0x%08lx\n", (long)docmem.start, (long)ctrl);
pci_write_config_dword(bridge, SCx200_DOCCS_BASE, docmem.start);
pci_write_config_dword(bridge, SCx200_DOCCS_CTRL, ctrl);
pmr = inl(scx200_cb_base + SCx200_PMR);
if (width == 8) {
pmr &= ~(1<<6);
} else {
pmr |= (1<<6);
}
outl(pmr, scx200_cb_base + SCx200_PMR);
}
printk(KERN_INFO NAME ": DOCCS mapped at 0x%lx-0x%lx, width %d\n",
docmem.start, docmem.end, width);
scx200_docflash_map.size = size;
if (width == 8)
scx200_docflash_map.bankwidth = 1;
else
scx200_docflash_map.bankwidth = 2;
simple_map_init(&scx200_docflash_map);
scx200_docflash_map.phys = docmem.start;
scx200_docflash_map.virt = ioremap(docmem.start, scx200_docflash_map.size);
if (!scx200_docflash_map.virt) {
printk(KERN_ERR NAME ": failed to ioremap the flash\n");
release_resource(&docmem);
return -EIO;
}
mymtd = do_map_probe(flashtype, &scx200_docflash_map);
if (!mymtd) {
printk(KERN_ERR NAME ": unable to detect flash\n");
iounmap(scx200_docflash_map.virt);
release_resource(&docmem);
return -ENXIO;
}
if (size < mymtd->size)
printk(KERN_WARNING NAME ": warning, flash mapping is smaller than flash size\n");
mymtd->owner = THIS_MODULE;
#ifdef CONFIG_MTD_PARTITIONS
partition_info[3].offset = mymtd->size-partition_info[3].size;
partition_info[2].size = partition_info[3].offset-partition_info[2].offset;
add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
#else
add_mtd_device(mymtd);
#endif
return 0;
}
static void __exit cleanup_scx200_docflash(void)
{
if (mymtd) {
#ifdef CONFIG_MTD_PARTITIONS
del_mtd_partitions(mymtd);
#else
del_mtd_device(mymtd);
#endif
map_destroy(mymtd);
}
if (scx200_docflash_map.virt) {
iounmap(scx200_docflash_map.virt);
release_resource(&docmem);
}
}
module_init(init_scx200_docflash);
module_exit(cleanup_scx200_docflash);
/*
Local variables:
compile-command: "make -k -C ../../.. SUBDIRS=drivers/mtd/maps modules"
c-basic-offset: 8
End:
*/

101
drivers/mtd/maps/sharpsl-flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,101 @@
/*
* sharpsl-flash.c
*
* Copyright (C) 2001 Lineo Japan, Inc.
* Copyright (C) 2002 SHARP
*
* $Id: sharpsl-flash.c,v 1.2 2004/11/24 20:38:06 rpurdie Exp $
*
* based on rpxlite.c,v 1.15 2001/10/02 15:05:14 dwmw2 Exp
* Handle mapping of the flash on the RPX Lite and CLLF boards
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#define WINDOW_ADDR 0x00000000
#define WINDOW_SIZE 0x01000000
#define BANK_WIDTH 2
static struct mtd_info *mymtd;
struct map_info sharpsl_map = {
.name = "sharpsl-flash",
.size = WINDOW_SIZE,
.bankwidth = BANK_WIDTH,
.phys = WINDOW_ADDR
};
static struct mtd_partition sharpsl_partitions[1] = {
{
name: "Filesystem",
size: 0x006d0000,
offset: 0x00120000
}
};
#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
int __init init_sharpsl(void)
{
struct mtd_partition *parts;
int nb_parts = 0;
char *part_type = "static";
printk(KERN_NOTICE "Sharp SL series flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
sharpsl_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!sharpsl_map.virt) {
printk("Failed to ioremap\n");
return -EIO;
}
mymtd = do_map_probe("map_rom", &sharpsl_map);
if (!mymtd) {
iounmap(sharpsl_map.virt);
return -ENXIO;
}
mymtd->owner = THIS_MODULE;
parts = sharpsl_partitions;
nb_parts = NB_OF(sharpsl_partitions);
printk(KERN_NOTICE "Using %s partision definition\n", part_type);
add_mtd_partitions(mymtd, parts, nb_parts);
return 0;
}
static void __exit cleanup_sharpsl(void)
{
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
if (sharpsl_map.virt) {
iounmap(sharpsl_map.virt);
sharpsl_map.virt = 0;
}
}
module_init(init_sharpsl);
module_exit(cleanup_sharpsl);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SHARP (Original: Arnold Christensen <AKC@pel.dk>)");
MODULE_DESCRIPTION("MTD map driver for SHARP SL series");

137
drivers/mtd/maps/solutionengine.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,137 @@
/*
* $Id: solutionengine.c,v 1.14 2004/09/16 23:27:14 gleixner Exp $
*
* Flash and EPROM on Hitachi Solution Engine and similar boards.
*
* (C) 2001 Red Hat, Inc.
*
* GPL'd
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/config.h>
#include <linux/errno.h>
static struct mtd_info *flash_mtd;
static struct mtd_info *eprom_mtd;
static struct mtd_partition *parsed_parts;
struct map_info soleng_eprom_map = {
.name = "Solution Engine EPROM",
.size = 0x400000,
.bankwidth = 4,
};
struct map_info soleng_flash_map = {
.name = "Solution Engine FLASH",
.size = 0x400000,
.bankwidth = 4,
};
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
#ifdef CONFIG_MTD_SUPERH_RESERVE
static struct mtd_partition superh_se_partitions[] = {
/* Reserved for boot code, read-only */
{
.name = "flash_boot",
.offset = 0x00000000,
.size = CONFIG_MTD_SUPERH_RESERVE,
.mask_flags = MTD_WRITEABLE,
},
/* All else is writable (e.g. JFFS) */
{
.name = "Flash FS",
.offset = MTDPART_OFS_NXTBLK,
.size = MTDPART_SIZ_FULL,
}
};
#endif /* CONFIG_MTD_SUPERH_RESERVE */
static int __init init_soleng_maps(void)
{
int nr_parts = 0;
/* First probe at offset 0 */
soleng_flash_map.phys = 0;
soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0);
soleng_eprom_map.phys = 0x01000000;
soleng_eprom_map.virt = (void __iomem *)P1SEGADDR(0x01000000);
simple_map_init(&soleng_eprom_map);
simple_map_init(&soleng_flash_map);
printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n");
flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map);
if (!flash_mtd) {
/* Not there. Try swapping */
printk(KERN_NOTICE "Probing for flash chips at 0x01000000:\n");
soleng_flash_map.phys = 0x01000000;
soleng_flash_map.virt = P2SEGADDR(0x01000000);
soleng_eprom_map.phys = 0;
soleng_eprom_map.virt = P1SEGADDR(0);
flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map);
if (!flash_mtd) {
/* Eep. */
printk(KERN_NOTICE "Flash chips not detected at either possible location.\n");
return -ENXIO;
}
}
printk(KERN_NOTICE "Solution Engine: Flash at 0x%08lx, EPROM at 0x%08lx\n",
soleng_flash_map.phys & 0x1fffffff,
soleng_eprom_map.phys & 0x1fffffff);
flash_mtd->owner = THIS_MODULE;
eprom_mtd = do_map_probe("map_rom", &soleng_eprom_map);
if (eprom_mtd) {
eprom_mtd->owner = THIS_MODULE;
add_mtd_device(eprom_mtd);
}
nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
#ifdef CONFIG_MTD_SUPERH_RESERVE
if (nr_parts <= 0) {
printk(KERN_NOTICE "Using configured partition at 0x%08x.\n",
CONFIG_MTD_SUPERH_RESERVE);
parsed_parts = superh_se_partitions;
nr_parts = sizeof(superh_se_partitions)/sizeof(*parsed_parts);
}
#endif /* CONFIG_MTD_SUPERH_RESERVE */
if (nr_parts > 0)
add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
else
add_mtd_device(flash_mtd);
return 0;
}
static void __exit cleanup_soleng_maps(void)
{
if (eprom_mtd) {
del_mtd_device(eprom_mtd);
map_destroy(eprom_mtd);
}
if (parsed_parts)
del_mtd_partitions(flash_mtd);
else
del_mtd_device(flash_mtd);
map_destroy(flash_mtd);
}
module_init(init_soleng_maps);
module_exit(cleanup_soleng_maps);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("MTD map driver for Hitachi SolutionEngine (and similar) boards");

177
drivers/mtd/maps/sun_uflash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,177 @@
/* $Id: sun_uflash.c,v 1.11 2004/11/04 13:24:15 gleixner Exp $
*
* sun_uflash - Driver implementation for user-programmable flash
* present on many Sun Microsystems SME boardsets.
*
* This driver does NOT provide access to the OBP-flash for
* safety reasons-- use <linux>/drivers/sbus/char/flash.c instead.
*
* Copyright (c) 2001 Eric Brower (ebrower@usa.net)
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <asm/ebus.h>
#include <asm/oplib.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#define UFLASH_OBPNAME "flashprom"
#define UFLASH_DEVNAME "userflash"
#define UFLASH_WINDOW_SIZE 0x200000
#define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */
MODULE_AUTHOR
("Eric Brower <ebrower@usa.net>");
MODULE_DESCRIPTION
("User-programmable flash device on Sun Microsystems boardsets");
MODULE_SUPPORTED_DEVICE
("userflash");
MODULE_LICENSE
("GPL");
static LIST_HEAD(device_list);
struct uflash_dev {
char * name; /* device name */
struct map_info map; /* mtd map info */
struct mtd_info * mtd; /* mtd info */
struct list_head list;
};
struct map_info uflash_map_templ = {
.name = "SUNW,???-????",
.size = UFLASH_WINDOW_SIZE,
.bankwidth = UFLASH_BUSWIDTH,
};
int uflash_devinit(struct linux_ebus_device* edev)
{
int iTmp, nregs;
struct linux_prom_registers regs[2];
struct uflash_dev *pdev;
iTmp = prom_getproperty(
edev->prom_node, "reg", (void *)regs, sizeof(regs));
if ((iTmp % sizeof(regs[0])) != 0) {
printk("%s: Strange reg property size %d\n",
UFLASH_DEVNAME, iTmp);
return -ENODEV;
}
nregs = iTmp / sizeof(regs[0]);
if (nregs != 1) {
/* Non-CFI userflash device-- once I find one we
* can work on supporting it.
*/
printk("%s: unsupported device at 0x%lx (%d regs): " \
"email ebrower@usa.net\n",
UFLASH_DEVNAME, edev->resource[0].start, nregs);
return -ENODEV;
}
if(0 == (pdev = kmalloc(sizeof(struct uflash_dev), GFP_KERNEL))) {
printk("%s: unable to kmalloc new device\n", UFLASH_DEVNAME);
return(-ENOMEM);
}
/* copy defaults and tweak parameters */
memcpy(&pdev->map, &uflash_map_templ, sizeof(uflash_map_templ));
pdev->map.size = regs[0].reg_size;
iTmp = prom_getproplen(edev->prom_node, "model");
pdev->name = kmalloc(iTmp, GFP_KERNEL);
prom_getstring(edev->prom_node, "model", pdev->name, iTmp);
if(0 != pdev->name && 0 < strlen(pdev->name)) {
pdev->map.name = pdev->name;
}
pdev->map.phys = edev->resource[0].start;
pdev->map.virt = ioremap_nocache(edev->resource[0].start, pdev->map.size);
if(0 == pdev->map.virt) {
printk("%s: failed to map device\n", __FUNCTION__);
kfree(pdev->name);
kfree(pdev);
return(-1);
}
simple_map_init(&pdev->map);
/* MTD registration */
pdev->mtd = do_map_probe("cfi_probe", &pdev->map);
if(0 == pdev->mtd) {
iounmap(pdev->map.virt);
kfree(pdev->name);
kfree(pdev);
return(-ENXIO);
}
list_add(&pdev->list, &device_list);
pdev->mtd->owner = THIS_MODULE;
add_mtd_device(pdev->mtd);
return(0);
}
static int __init uflash_init(void)
{
struct linux_ebus *ebus = NULL;
struct linux_ebus_device *edev = NULL;
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {
if (!strcmp(edev->prom_name, UFLASH_OBPNAME)) {
if(0 > prom_getproplen(edev->prom_node, "user")) {
DEBUG(2, "%s: ignoring device at 0x%lx\n",
UFLASH_DEVNAME, edev->resource[0].start);
} else {
uflash_devinit(edev);
}
}
}
}
if(list_empty(&device_list)) {
printk("%s: unable to locate device\n", UFLASH_DEVNAME);
return -ENODEV;
}
return(0);
}
static void __exit uflash_cleanup(void)
{
struct list_head *udevlist;
struct uflash_dev *udev;
list_for_each(udevlist, &device_list) {
udev = list_entry(udevlist, struct uflash_dev, list);
DEBUG(2, "%s: removing device %s\n",
UFLASH_DEVNAME, udev->name);
if(0 != udev->mtd) {
del_mtd_device(udev->mtd);
map_destroy(udev->mtd);
}
if(0 != udev->map.virt) {
iounmap(udev->map.virt);
udev->map.virt = NULL;
}
if(0 != udev->name) {
kfree(udev->name);
}
kfree(udev);
}
}
module_init(uflash_init);
module_exit(uflash_cleanup);

263
drivers/mtd/maps/tqm8xxl.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,263 @@
/*
* Handle mapping of the flash memory access routines
* on TQM8xxL based devices.
*
* $Id: tqm8xxl.c,v 1.13 2004/10/20 22:21:53 dwmw2 Exp $
*
* based on rpxlite.c
*
* Copyright(C) 2001 Kirk Lee <kirk@hpc.ee.ntu.edu.tw>
*
* This code is GPLed
*
*/
/*
* According to TQM8xxL hardware manual, TQM8xxL series have
* following flash memory organisations:
* | capacity | | chip type | | bank0 | | bank1 |
* 2MiB 512Kx16 2MiB 0
* 4MiB 1Mx16 4MiB 0
* 8MiB 1Mx16 4MiB 4MiB
* Thus, we choose CONFIG_MTD_CFI_I2 & CONFIG_MTD_CFI_B4 at
* kernel configuration.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#define FLASH_ADDR 0x40000000
#define FLASH_SIZE 0x00800000
#define FLASH_BANK_MAX 4
// trivial struct to describe partition information
struct mtd_part_def
{
int nums;
unsigned char *type;
struct mtd_partition* mtd_part;
};
//static struct mtd_info *mymtd;
static struct mtd_info* mtd_banks[FLASH_BANK_MAX];
static struct map_info* map_banks[FLASH_BANK_MAX];
static struct mtd_part_def part_banks[FLASH_BANK_MAX];
static unsigned long num_banks;
static void __iomem *start_scan_addr;
/*
* Here are partition information for all known TQM8xxL series devices.
* See include/linux/mtd/partitions.h for definition of the mtd_partition
* structure.
*
* The *_max_flash_size is the maximum possible mapped flash size which
* is not necessarily the actual flash size. It must correspond to the
* value specified in the mapping definition defined by the
* "struct map_desc *_io_desc" for the corresponding machine.
*/
#ifdef CONFIG_MTD_PARTITIONS
/* Currently, TQM8xxL has upto 8MiB flash */
static unsigned long tqm8xxl_max_flash_size = 0x00800000;
/* partition definition for first flash bank
* (cf. "drivers/char/flash_config.c")
*/
static struct mtd_partition tqm8xxl_partitions[] = {
{
.name = "ppcboot",
.offset = 0x00000000,
.size = 0x00020000, /* 128KB */
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
{
.name = "kernel", /* default kernel image */
.offset = 0x00020000,
.size = 0x000e0000,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
{
.name = "user",
.offset = 0x00100000,
.size = 0x00100000,
},
{
.name = "initrd",
.offset = 0x00200000,
.size = 0x00200000,
}
};
/* partition definition for second flash bank */
static struct mtd_partition tqm8xxl_fs_partitions[] = {
{
.name = "cramfs",
.offset = 0x00000000,
.size = 0x00200000,
},
{
.name = "jffs",
.offset = 0x00200000,
.size = 0x00200000,
//.size = MTDPART_SIZ_FULL,
}
};
#endif
int __init init_tqm_mtd(void)
{
int idx = 0, ret = 0;
unsigned long flash_addr, flash_size, mtd_size = 0;
/* pointer to TQM8xxL board info data */
bd_t *bd = (bd_t *)__res;
flash_addr = bd->bi_flashstart;
flash_size = bd->bi_flashsize;
//request maximum flash size address space
start_scan_addr = ioremap(flash_addr, flash_size);
if (!start_scan_addr) {
printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr);
return -EIO;
}
for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
if(mtd_size >= flash_size)
break;
printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx);
map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL);
if(map_banks[idx] == NULL) {
ret = -ENOMEM;
/* FIXME: What if some MTD devices were probed already? */
goto error_mem;
}
memset((void *)map_banks[idx], 0, sizeof(struct map_info));
map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
if (!map_banks[idx]->name) {
ret = -ENOMEM;
/* FIXME: What if some MTD devices were probed already? */
goto error_mem;
}
sprintf(map_banks[idx]->name, "TQM8xxL%d", idx);
map_banks[idx]->size = flash_size;
map_banks[idx]->bankwidth = 4;
simple_map_init(map_banks[idx]);
map_banks[idx]->virt = start_scan_addr;
map_banks[idx]->phys = flash_addr;
/* FIXME: This looks utterly bogus, but I'm trying to
preserve the behaviour of the original (shown here)...
map_banks[idx]->map_priv_1 =
start_scan_addr + ((idx > 0) ?
(mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0);
*/
if (idx && mtd_banks[idx-1]) {
map_banks[idx]->virt += mtd_banks[idx-1]->size;
map_banks[idx]->phys += mtd_banks[idx-1]->size;
}
//start to probe flash chips
mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]);
if (mtd_banks[idx]) {
mtd_banks[idx]->owner = THIS_MODULE;
mtd_size += mtd_banks[idx]->size;
num_banks++;
printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks,
mtd_banks[idx]->name, mtd_banks[idx]->size);
}
}
/* no supported flash chips found */
if (!num_banks) {
printk(KERN_NOTICE "TQM8xxL: No support flash chips found!\n");
ret = -ENXIO;
goto error_mem;
}
#ifdef CONFIG_MTD_PARTITIONS
/*
* Select Static partition definitions
*/
part_banks[0].mtd_part = tqm8xxl_partitions;
part_banks[0].type = "Static image";
part_banks[0].nums = ARRAY_SIZE(tqm8xxl_partitions);
part_banks[1].mtd_part = tqm8xxl_fs_partitions;
part_banks[1].type = "Static file system";
part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions);
for(idx = 0; idx < num_banks ; idx++) {
if (part_banks[idx].nums == 0) {
printk(KERN_NOTICE "TQM flash%d: no partition info available, registering whole flash at once\n", idx);
add_mtd_device(mtd_banks[idx]);
} else {
printk(KERN_NOTICE "TQM flash%d: Using %s partition definition\n",
idx, part_banks[idx].type);
add_mtd_partitions(mtd_banks[idx], part_banks[idx].mtd_part,
part_banks[idx].nums);
}
}
#else
printk(KERN_NOTICE "TQM flash: registering %d whole flash banks at once\n", num_banks);
for(idx = 0 ; idx < num_banks ; idx++)
add_mtd_device(mtd_banks[idx]);
#endif
return 0;
error_mem:
for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
if(map_banks[idx] != NULL) {
if(map_banks[idx]->name != NULL) {
kfree(map_banks[idx]->name);
map_banks[idx]->name = NULL;
}
kfree(map_banks[idx]);
map_banks[idx] = NULL;
}
}
error:
iounmap(start_scan_addr);
return ret;
}
static void __exit cleanup_tqm_mtd(void)
{
unsigned int idx = 0;
for(idx = 0 ; idx < num_banks ; idx++) {
/* destroy mtd_info previously allocated */
if (mtd_banks[idx]) {
del_mtd_partitions(mtd_banks[idx]);
map_destroy(mtd_banks[idx]);
}
/* release map_info not used anymore */
kfree(map_banks[idx]->name);
kfree(map_banks[idx]);
}
if (start_scan_addr) {
iounmap(start_scan_addr);
start_scan_addr = 0;
}
}
module_init(init_tqm_mtd);
module_exit(cleanup_tqm_mtd);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kirk Lee <kirk@hpc.ee.ntu.edu.tw>");
MODULE_DESCRIPTION("MTD map driver for TQM8xxL boards");

141
drivers/mtd/maps/ts5500_flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,141 @@
/*
* ts5500_flash.c -- MTD map driver for Technology Systems TS-5500 board
*
* Copyright (C) 2004 Sean Young <sean@mess.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Note:
* - In order for detection to work, jumper 3 must be set.
* - Drive A and B use a proprietary FTL from General Software which isn't
* supported as of yet so standard drives can't be mounted; you can create
* your own (e.g. jffs) file system.
* - If you have created your own jffs file system and the bios overwrites
* it during boot, try disabling Drive A: and B: in the boot order.
*
* $Id: ts5500_flash.c,v 1.2 2004/11/28 09:40:40 dwmw2 Exp $
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
#endif
#define WINDOW_ADDR 0x09400000
#define WINDOW_SIZE 0x00200000
static struct map_info ts5500_map = {
.name = "TS-5500 Flash",
.size = WINDOW_SIZE,
.bankwidth = 1,
.phys = WINDOW_ADDR
};
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition ts5500_partitions[] = {
{
.name = "Drive A",
.offset = 0,
.size = 0x0e0000
},
{
.name = "BIOS",
.offset = 0x0e0000,
.size = 0x020000,
},
{
.name = "Drive B",
.offset = 0x100000,
.size = 0x100000
}
};
#define NUM_PARTITIONS (sizeof(ts5500_partitions)/sizeof(struct mtd_partition))
#endif
static struct mtd_info *mymtd;
static int __init init_ts5500_map(void)
{
int rc = 0;
ts5500_map.virt = ioremap_nocache(ts5500_map.phys, ts5500_map.size);
if(!ts5500_map.virt) {
printk(KERN_ERR "Failed to ioremap_nocache\n");
rc = -EIO;
goto err_out_ioremap;
}
simple_map_init(&ts5500_map);
mymtd = do_map_probe("jedec_probe", &ts5500_map);
if(!mymtd)
mymtd = do_map_probe("map_rom", &ts5500_map);
if(!mymtd) {
rc = -ENXIO;
goto err_out_map;
}
mymtd->owner = THIS_MODULE;
#ifdef CONFIG_MTD_PARTITIONS
add_mtd_partitions(mymtd, ts5500_partitions, NUM_PARTITIONS);
#else
add_mtd_device(mymtd);
#endif
return 0;
err_out_map:
map_destroy(mymtd);
err_out_ioremap:
iounmap(ts5500_map.virt);
return rc;
}
static void __exit cleanup_ts5500_map(void)
{
if (mymtd) {
#ifdef CONFIG_MTD_PARTITIONS
del_mtd_partitions(mymtd);
#else
del_mtd_device(mymtd);
#endif
map_destroy(mymtd);
}
if (ts5500_map.virt) {
iounmap(ts5500_map.virt);
ts5500_map.virt = NULL;
}
}
module_init(init_ts5500_map);
module_exit(cleanup_ts5500_map);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sean Young <sean@mess.org>");
MODULE_DESCRIPTION("MTD map driver for Techology Systems TS-5500 board");

108
drivers/mtd/maps/tsunami_flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,108 @@
/*
* tsunami_flash.c
*
* flash chip on alpha ds10...
* $Id: tsunami_flash.c,v 1.9 2004/07/14 09:52:55 dwmw2 Exp $
*/
#include <asm/io.h>
#include <asm/core_tsunami.h>
#include <linux/init.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#define FLASH_ENABLE_PORT 0x00C00001
#define FLASH_ENABLE_BYTE 0x01
#define FLASH_DISABLE_BYTE 0x00
#define MAX_TIG_FLASH_SIZE (12*1024*1024)
static inline map_word tsunami_flash_read8(struct map_info *map, unsigned long offset)
{
map_word val;
val.x[0] = tsunami_tig_readb(offset);
return val;
}
static void tsunami_flash_write8(struct map_info *map, map_word value, unsigned long offset)
{
tsunami_tig_writeb(value.x[0], offset);
}
static void tsunami_flash_copy_from(
struct map_info *map, void *addr, unsigned long offset, ssize_t len)
{
unsigned char *dest;
dest = addr;
while(len && (offset < MAX_TIG_FLASH_SIZE)) {
*dest = tsunami_tig_readb(offset);
offset++;
dest++;
len--;
}
}
static void tsunami_flash_copy_to(
struct map_info *map, unsigned long offset,
const void *addr, ssize_t len)
{
const unsigned char *src;
src = addr;
while(len && (offset < MAX_TIG_FLASH_SIZE)) {
tsunami_tig_writeb(*src, offset);
offset++;
src++;
len--;
}
}
/*
* Deliberately don't provide operations wider than 8 bits. I don't
* have then and it scares me to think how you could mess up if
* you tried to use them. Buswidth is correctly so I'm safe.
*/
static struct map_info tsunami_flash_map = {
.name = "flash chip on the Tsunami TIG bus",
.size = MAX_TIG_FLASH_SIZE,
.phys = NO_XIP;
.bankwidth = 1,
.read = tsunami_flash_read8,
.copy_from = tsunami_flash_copy_from,
.write = tsunami_flash_write8,
.copy_to = tsunami_flash_copy_to,
};
static struct mtd_info *tsunami_flash_mtd;
static void __exit cleanup_tsunami_flash(void)
{
struct mtd_info *mtd;
mtd = tsunami_flash_mtd;
if (mtd) {
del_mtd_device(mtd);
map_destroy(mtd);
}
tsunami_flash_mtd = 0;
}
static int __init init_tsunami_flash(void)
{
static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
char **type;
tsunami_tig_writeb(FLASH_ENABLE_BYTE, FLASH_ENABLE_PORT);
tsunami_flash_mtd = 0;
type = rom_probe_types;
for(; !tsunami_flash_mtd && *type; type++) {
tsunami_flash_mtd = do_map_probe(*type, &tsunami_flash_map);
}
if (tsunami_flash_mtd) {
tsunami_flash_mtd->owner = THIS_MODULE;
add_mtd_device(tsunami_flash_mtd);
return 0;
}
return -ENXIO;
}
module_init(init_tsunami_flash);
module_exit(cleanup_tsunami_flash);

127
drivers/mtd/maps/uclinux.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,127 @@
/****************************************************************************/
/*
* uclinux.c -- generic memory mapped MTD driver for uclinux
*
* (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
*
* $Id: uclinux.c,v 1.10 2005/01/05 18:05:13 dwmw2 Exp $
*/
/****************************************************************************/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/root_dev.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
/****************************************************************************/
/****************************************************************************/
struct map_info uclinux_ram_map = {
.name = "RAM",
};
struct mtd_info *uclinux_ram_mtdinfo;
/****************************************************************************/
struct mtd_partition uclinux_romfs[] = {
{ .name = "ROMfs" }
};
#define NUM_PARTITIONS (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0]))
/****************************************************************************/
int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char **mtdbuf)
{
struct map_info *map = mtd->priv;
*mtdbuf = (u_char *) (map->virt + ((int) from));
*retlen = len;
return(0);
}
/****************************************************************************/
int __init uclinux_mtd_init(void)
{
struct mtd_info *mtd;
struct map_info *mapp;
extern char _ebss;
mapp = &uclinux_ram_map;
mapp->phys = (unsigned long) &_ebss;
mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8)));
mapp->bankwidth = 4;
printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
(int) mapp->map_priv_2, (int) mapp->size);
mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
if (mapp->virt == 0) {
printk("uclinux[mtd]: ioremap_nocache() failed\n");
return(-EIO);
}
simple_map_init(mapp);
mtd = do_map_probe("map_ram", mapp);
if (!mtd) {
printk("uclinux[mtd]: failed to find a mapping?\n");
iounmap(mapp->virt);
return(-ENXIO);
}
mtd->owner = THIS_MODULE;
mtd->point = uclinux_point;
mtd->priv = mapp;
uclinux_ram_mtdinfo = mtd;
add_mtd_partitions(mtd, uclinux_romfs, NUM_PARTITIONS);
printk("uclinux[mtd]: set %s to be root filesystem\n",
uclinux_romfs[0].name);
ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
put_mtd_device(mtd);
return(0);
}
/****************************************************************************/
void __exit uclinux_mtd_cleanup(void)
{
if (uclinux_ram_mtdinfo) {
del_mtd_partitions(uclinux_ram_mtdinfo);
map_destroy(uclinux_ram_mtdinfo);
uclinux_ram_mtdinfo = NULL;
}
if (uclinux_ram_map.map_priv_1) {
iounmap((void *) uclinux_ram_map.virt);
uclinux_ram_map.virt = 0;
}
}
/****************************************************************************/
module_init(uclinux_mtd_init);
module_exit(uclinux_mtd_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
MODULE_DESCRIPTION("Generic RAM based MTD for uClinux");
/****************************************************************************/

198
drivers/mtd/maps/vmax301.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,198 @@
// $Id: vmax301.c,v 1.30 2004/07/12 22:38:29 dwmw2 Exp $
/* ######################################################################
Tempustech VMAX SBC301 MTD Driver.
The VMAx 301 is a SBC based on . It
comes with three builtin AMD 29F016B flash chips and a socket for SRAM or
more flash. Each unit has it's own 8k mapping into a settable region
(0xD8000). There are two 8k mappings for each MTD, the first is always set
to the lower 8k of the device the second is paged. Writing a 16 bit page
value to anywhere in the first 8k will cause the second 8k to page around.
To boot the device a bios extension must be installed into the first 8k
of flash that is smart enough to copy itself down, page in the rest of
itself and begin executing.
##################################################################### */
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <asm/io.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#define WINDOW_START 0xd8000
#define WINDOW_LENGTH 0x2000
#define WINDOW_SHIFT 25
#define WINDOW_MASK 0x1FFF
/* Actually we could use two spinlocks, but we'd have to have
more private space in the struct map_info. We lose a little
performance like this, but we'd probably lose more by having
the extra indirection from having one of the map->map_priv
fields pointing to yet another private struct.
*/
static DEFINE_SPINLOCK(vmax301_spin);
static void __vmax301_page(struct map_info *map, unsigned long page)
{
writew(page, map->map_priv_2 - WINDOW_LENGTH);
map->map_priv_1 = page;
}
static inline void vmax301_page(struct map_info *map,
unsigned long ofs)
{
unsigned long page = (ofs >> WINDOW_SHIFT);
if (map->map_priv_1 != page)
__vmax301_page(map, page);
}
static map_word vmax301_read8(struct map_info *map, unsigned long ofs)
{
map_word ret;
spin_lock(&vmax301_spin);
vmax301_page(map, ofs);
ret.x[0] = readb(map->map_priv_2 + (ofs & WINDOW_MASK));
spin_unlock(&vmax301_spin);
return ret;
}
static void vmax301_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
while(len) {
unsigned long thislen = len;
if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
spin_lock(&vmax301_spin);
vmax301_page(map, from);
memcpy_fromio(to, map->map_priv_2 + from, thislen);
spin_unlock(&vmax301_spin);
to += thislen;
from += thislen;
len -= thislen;
}
}
static void vmax301_write8(struct map_info *map, map_word d, unsigned long adr)
{
spin_lock(&vmax301_spin);
vmax301_page(map, adr);
writeb(d.x[0], map->map_priv_2 + (adr & WINDOW_MASK));
spin_unlock(&vmax301_spin);
}
static void vmax301_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
while(len) {
unsigned long thislen = len;
if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
spin_lock(&vmax301_spin);
vmax301_page(map, to);
memcpy_toio(map->map_priv_2 + to, from, thislen);
spin_unlock(&vmax301_spin);
to += thislen;
from += thislen;
len -= thislen;
}
}
static struct map_info vmax_map[2] = {
{
.name = "VMAX301 Internal Flash",
.phys = NO_XIP,
.size = 3*2*1024*1024,
.bankwidth = 1,
.read = vmax301_read8,
.copy_from = vmax301_copy_from,
.write = vmax301_write8,
.copy_to = vmax301_copy_to,
.map_priv_1 = WINDOW_START + WINDOW_LENGTH,
.map_priv_2 = 0xFFFFFFFF
},
{
.name = "VMAX301 Socket",
.phys = NO_XIP,
.size = 0,
.bankwidth = 1,
.read = vmax301_read8,
.copy_from = vmax301_copy_from,
.write = vmax301_write8,
.copy_to = vmax301_copy_to,
.map_priv_1 = WINDOW_START + (3*WINDOW_LENGTH),
.map_priv_2 = 0xFFFFFFFF
}
};
static struct mtd_info *vmax_mtd[2] = {NULL, NULL};
static void __exit cleanup_vmax301(void)
{
int i;
for (i=0; i<2; i++) {
if (vmax_mtd[i]) {
del_mtd_device(vmax_mtd[i]);
map_destroy(vmax_mtd[i]);
}
}
iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START);
}
int __init init_vmax301(void)
{
int i;
unsigned long iomapadr;
// Print out our little header..
printk("Tempustech VMAX 301 MEM:0x%x-0x%x\n",WINDOW_START,
WINDOW_START+4*WINDOW_LENGTH);
iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH*4);
if (!iomapadr) {
printk("Failed to ioremap memory region\n");
return -EIO;
}
/* Put the address in the map's private data area.
We store the actual MTD IO address rather than the
address of the first half, because it's used more
often.
*/
vmax_map[0].map_priv_2 = iomapadr + WINDOW_START;
vmax_map[1].map_priv_2 = iomapadr + (3*WINDOW_START);
for (i=0; i<2; i++) {
vmax_mtd[i] = do_map_probe("cfi_probe", &vmax_map[i]);
if (!vmax_mtd[i])
vmax_mtd[i] = do_map_probe("jedec", &vmax_map[i]);
if (!vmax_mtd[i])
vmax_mtd[i] = do_map_probe("map_ram", &vmax_map[i]);
if (!vmax_mtd[i])
vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]);
if (vmax_mtd[i]) {
vmax_mtd[i]->owner = THIS_MODULE;
add_mtd_device(vmax_mtd[i]);
}
}
if (!vmax_mtd[1] && !vmax_mtd[2]) {
iounmap((void *)iomapadr);
return -ENXIO;
}
return 0;
}
module_init(init_vmax301);
module_exit(cleanup_vmax301);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("MTD map driver for Tempustech VMAX SBC301 board");

122
drivers/mtd/maps/walnut.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,122 @@
/*
* $Id: walnut.c,v 1.2 2004/12/10 12:07:42 holindho Exp $
*
* Mapping for Walnut flash
* (used ebony.c as a "framework")
*
* Heikki Lindholm <holindho@infradead.org>
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/config.h>
#include <linux/version.h>
#include <asm/io.h>
#include <asm/ibm4xx.h>
#include <platforms/4xx/walnut.h>
/* these should be in platforms/4xx/walnut.h ? */
#define WALNUT_FLASH_ONBD_N(x) (x & 0x02)
#define WALNUT_FLASH_SRAM_SEL(x) (x & 0x01)
#define WALNUT_FLASH_LOW 0xFFF00000
#define WALNUT_FLASH_HIGH 0xFFF80000
#define WALNUT_FLASH_SIZE 0x80000
static struct mtd_info *flash;
static struct map_info walnut_map = {
.name = "Walnut flash",
.size = WALNUT_FLASH_SIZE,
.bankwidth = 1,
};
/* Actually, OpenBIOS is the last 128 KiB of the flash - better
* partitioning could be made */
static struct mtd_partition walnut_partitions[] = {
{
.name = "OpenBIOS",
.offset = 0x0,
.size = WALNUT_FLASH_SIZE,
/*.mask_flags = MTD_WRITEABLE, */ /* force read-only */
}
};
int __init init_walnut(void)
{
u8 fpga_brds1;
void *fpga_brds1_adr;
void *fpga_status_adr;
unsigned long flash_base;
/* this should already be mapped (platform/4xx/walnut.c) */
fpga_status_adr = ioremap(WALNUT_FPGA_BASE, 8);
if (!fpga_status_adr)
return -ENOMEM;
fpga_brds1_adr = fpga_status_adr+5;
fpga_brds1 = readb(fpga_brds1_adr);
/* iounmap(fpga_status_adr); */
if (WALNUT_FLASH_ONBD_N(fpga_brds1)) {
printk("The on-board flash is disabled (U79 sw 5)!");
return -EIO;
}
if (WALNUT_FLASH_SRAM_SEL(fpga_brds1))
flash_base = WALNUT_FLASH_LOW;
else
flash_base = WALNUT_FLASH_HIGH;
walnut_map.phys = flash_base;
walnut_map.virt =
(void __iomem *)ioremap(flash_base, walnut_map.size);
if (!walnut_map.virt) {
printk("Failed to ioremap flash.\n");
return -EIO;
}
simple_map_init(&walnut_map);
flash = do_map_probe("jedec_probe", &walnut_map);
if (flash) {
flash->owner = THIS_MODULE;
add_mtd_partitions(flash, walnut_partitions,
ARRAY_SIZE(walnut_partitions));
} else {
printk("map probe failed for flash\n");
return -ENXIO;
}
return 0;
}
static void __exit cleanup_walnut(void)
{
if (flash) {
del_mtd_partitions(flash);
map_destroy(flash);
}
if (walnut_map.virt) {
iounmap((void *)walnut_map.virt);
walnut_map.virt = 0;
}
}
module_init(init_walnut);
module_exit(cleanup_walnut);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Heikki Lindholm <holindho@infradead.org>");
MODULE_DESCRIPTION("MTD map and partitions for IBM 405GP Walnut boards");

181
drivers/mtd/maps/wr_sbc82xx_flash.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,181 @@
/*
* $Id: wr_sbc82xx_flash.c,v 1.7 2004/11/04 13:24:15 gleixner Exp $
*
* Map for flash chips on Wind River PowerQUICC II SBC82xx board.
*
* Copyright (C) 2004 Red Hat, Inc.
*
* Author: David Woodhouse <dwmw2@infradead.org>
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/config.h>
#include <linux/mtd/partitions.h>
#include <asm/immap_cpm2.h>
static struct mtd_info *sbcmtd[3];
static struct mtd_partition *sbcmtd_parts[3];
struct map_info sbc82xx_flash_map[3] = {
{.name = "Boot flash"},
{.name = "Alternate boot flash"},
{.name = "User flash"}
};
static struct mtd_partition smallflash_parts[] = {
{
.name = "space",
.size = 0x100000,
.offset = 0,
}, {
.name = "bootloader",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND,
}
};
static struct mtd_partition bigflash_parts[] = {
{
.name = "bootloader",
.size = 0x00100000,
.offset = 0,
}, {
.name = "file system",
.size = 0x01f00000,
.offset = MTDPART_OFS_APPEND,
}, {
.name = "boot config",
.size = 0x00100000,
.offset = MTDPART_OFS_APPEND,
}, {
.name = "space",
.size = 0x01f00000,
.offset = MTDPART_OFS_APPEND,
}
};
static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
#define init_sbc82xx_one_flash(map, br, or) \
do { \
(map).phys = (br & 1) ? (br & 0xffff8000) : 0; \
(map).size = (br & 1) ? (~(or & 0xffff8000) + 1) : 0; \
switch (br & 0x00001800) { \
case 0x00000000: \
case 0x00000800: (map).bankwidth = 1; break; \
case 0x00001000: (map).bankwidth = 2; break; \
case 0x00001800: (map).bankwidth = 4; break; \
} \
} while (0);
int __init init_sbc82xx_flash(void)
{
volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl;
int bigflash;
int i;
#ifdef CONFIG_SBC8560
mc = ioremap(0xff700000 + 0x5000, sizeof(memctl_cpm2_t));
#else
mc = &cpm2_immr->im_memctl;
#endif
bigflash = 1;
if ((mc->memc_br0 & 0x00001800) == 0x00001800)
bigflash = 0;
init_sbc82xx_one_flash(sbc82xx_flash_map[0], mc->memc_br0, mc->memc_or0);
init_sbc82xx_one_flash(sbc82xx_flash_map[1], mc->memc_br6, mc->memc_or6);
init_sbc82xx_one_flash(sbc82xx_flash_map[2], mc->memc_br1, mc->memc_or1);
#ifdef CONFIG_SBC8560
iounmap((void *) mc);
#endif
for (i=0; i<3; i++) {
int8_t flashcs[3] = { 0, 6, 1 };
int nr_parts;
printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
sbc82xx_flash_map[i].name,
(sbc82xx_flash_map[i].size >> 20),
flashcs[i]);
if (!sbc82xx_flash_map[i].phys) {
/* We know it can't be at zero. */
printk("): disabled by bootloader.\n");
continue;
}
printk(" at %08lx)\n", sbc82xx_flash_map[i].phys);
sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size);
if (!sbc82xx_flash_map[i].virt) {
printk("Failed to ioremap\n");
continue;
}
simple_map_init(&sbc82xx_flash_map[i]);
sbcmtd[i] = do_map_probe("cfi_probe", &sbc82xx_flash_map[i]);
if (!sbcmtd[i])
continue;
sbcmtd[i]->owner = THIS_MODULE;
nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes,
&sbcmtd_parts[i], 0);
if (nr_parts > 0) {
add_mtd_partitions (sbcmtd[i], sbcmtd_parts[i], nr_parts);
continue;
}
/* No partitioning detected. Use default */
if (i == 2) {
add_mtd_device(sbcmtd[i]);
} else if (i == bigflash) {
add_mtd_partitions (sbcmtd[i], bigflash_parts, ARRAY_SIZE(bigflash_parts));
} else {
add_mtd_partitions (sbcmtd[i], smallflash_parts, ARRAY_SIZE(smallflash_parts));
}
}
return 0;
}
static void __exit cleanup_sbc82xx_flash(void)
{
int i;
for (i=0; i<3; i++) {
if (!sbcmtd[i])
continue;
if (i<2 || sbcmtd_parts[i])
del_mtd_partitions(sbcmtd[i]);
else
del_mtd_device(sbcmtd[i]);
kfree(sbcmtd_parts[i]);
map_destroy(sbcmtd[i]);
iounmap((void *)sbc82xx_flash_map[i].virt);
sbc82xx_flash_map[i].virt = 0;
}
}
module_init(init_sbc82xx_flash);
module_exit(cleanup_sbc82xx_flash);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("Flash map driver for WindRiver PowerQUICC II");